2010-10-15 13 views
14

वाले एक्सएमएल दस्तावेज़ों पर XPath का उपयोग कैसे करें मैं डिफ़ॉल्ट नामस्थान वाले एक्सएमएल दस्तावेज़ में हेरफेर करना चाहता हूं लेकिन कोई उपसर्ग नहीं। क्या नेमस्पेस यूरी के बिना xpath का उपयोग करने का कोई तरीका है जैसे कि कोई नामस्थान नहीं है?
मेरा मानना ​​है कि यह संभव होना चाहिए यदि हम दस्तावेज़ की नेमस्पेस संपत्ति संपत्ति सेट करें FilderFactory को झूठी। लेकिन मेरे मामले में यह काम नहीं कर रहा है।
क्या मेरी समझ गलत है या मैं कोड में कुछ गलती कर रहा हूं?डिफ़ॉल्ट नामस्थान

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
    domFactory.setNamespaceAware(false); 
    try { 
     DocumentBuilder builder = domFactory.newDocumentBuilder(); 
     Document dDoc = builder.parse("E:/test.xml"); 

     XPath xPath = XPathFactory.newInstance().newXPath(); 
     NodeList nl = (NodeList) xPath.evaluate("//author", dDoc, XPathConstants.NODESET); 
     System.out.println(nl.getLength()); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

यहाँ मेरी xml है:

यहाँ मेरी कोड है

<?xml version="1.0" encoding="UTF-8"?> 
<root xmlns="http://www.mydomain.com/schema"> 
    <author> 
    <book title="t1"/> 
    <book title="t2"/> 
    </author> 
</root> 
+0

पर निर्भरता इस एक ही समस्या एक पूछे जाने वाले प्रश्न के लिए Default XML namespace, JDOM, and XPath belwood

उत्तर

21

डिफ़ॉल्ट नाम स्थान (कोई उपसर्ग) का उपयोग करता है एक दस्तावेज के लिए XPath प्रसंस्करण XPath प्रसंस्करण रूप में ही है उपसर्ग का उपयोग करने वाले दस्तावेज़ के लिए:

नामस्थान योग्य दस्तावेज़ों के लिए आप XPath निष्पादित करते समय नामस्थान कॉन्टेक्स्ट का उपयोग कर सकते हैं। नेमस्पेस कॉन्टेक्स्ट से मेल खाने के लिए आपको XPath में टुकड़ों को उपसर्ग करना होगा। आपके द्वारा उपयोग किए जाने वाले उपसर्गों को दस्तावेज़ में प्रयुक्त उपसर्गों से मेल खाने की आवश्यकता नहीं है।

यह इस प्रकार से अपने कोड के साथ दिखाई देता है:

import java.util.Iterator; 
import javax.xml.namespace.NamespaceContext; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathFactory; 
import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 

public class Demo { 

    public static void main(String[] args) { 
     DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
     domFactory.setNamespaceAware(true); 
     try { 
      DocumentBuilder builder = domFactory.newDocumentBuilder(); 
      Document dDoc = builder.parse("E:/test.xml"); 

      XPath xPath = XPathFactory.newInstance().newXPath(); 
      xPath.setNamespaceContext(new MyNamespaceContext()); 
      NodeList nl = (NodeList) xPath.evaluate("/ns:root/ns:author", dDoc, XPathConstants.NODESET); 
      System.out.println(nl.getLength()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static class MyNamespaceContext implements NamespaceContext { 

     public String getNamespaceURI(String prefix) { 
      if("ns".equals(prefix)) { 
       return "http://www.mydomain.com/schema"; 
      } 
      return null; 
     } 

     public String getPrefix(String namespaceURI) { 
      return null; 
     } 

     public Iterator getPrefixes(String namespaceURI) { 
      return null; 
     } 

    } 

} 

नोट: मैं भी ठीक किया XPath Dennis ने सुझाव दिया करते थे।

निम्नलिखित भी काम करने के लिए प्रकट होता है, और अपने मूल प्रश्न के करीब है:

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathFactory; 

import org.w3c.dom.Document; 
import org.w3c.dom.NodeList; 

public class Demo { 

    public static void main(String[] args) { 
     DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
     try { 
      DocumentBuilder builder = domFactory.newDocumentBuilder(); 
      Document dDoc = builder.parse("E:/test.xml"); 

      XPath xPath = XPathFactory.newInstance().newXPath(); 
      NodeList nl = (NodeList) xPath.evaluate("/root/author", dDoc, XPathConstants.NODESET); 
      System.out.println(nl.getLength()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

} 
+1

+1 अच्छा स्पष्टीकरण की तरह लग रहा है। –

+0

तो मुझे नामांकित परिदृश्य में जाना होगा। खैर, एक अच्छा विचार है, लेकिन मैं ऐसा करने में नरक में रहूंगा। मेरे पास बहुत सारे कोड हैं जो वर्तमान में xpath का उपयोग करके नामस्थान के बिना एक्सएमएल को संभालने में हैं। मुझे सत्यापन (आईडीई और प्रोग्रामेटिक रूप से) उद्देश्य के लिए डिफ़ॉल्ट नामस्थान जोड़ना पड़ा। क्या एक पत्थर से दो पक्षियों को मारने का कोई तरीका है?मेरा मतलब है मैं xPath अभिव्यक्ति के सभी संपादित करने के लिए नहीं हो सकता है, और एक ही समय में दस्तावेज़ दोनों आईडीई में और प्रोग्राम के रूप में मान्य हो सकता है? – WSK

+0

मैंने नामस्थान को हटाने का विचार किया। उस स्थिति में मुझे xpath समस्या का सामना नहीं करना पड़ेगा और प्रोग्रामेटिक सत्यापन के लिए मैं रनटाइम पर नेमस्पेस जोड़ सकता हूं। शायद, मुझे सत्यापन से पहले केवल अपने दस्तावेज़ों को पार्स करना होगा। यह स्वीकार्य हो सकता है लेकिन ऐसा करने के बाद, मुझे आईडीई द्वारा अपने एक्सएमएल दस्तावेज़ों को सत्यापित करने का कोई तरीका नहीं दिखता है। कोई अन्य विचार? – WSK

1

Blaise Doughan सही है, संलग्न कोड सही है।
समस्या कहीं elese था। मैं एक्लिप्स आईडीई में एप्लिकेशन लॉन्चर के माध्यम से अपने सभी परीक्षण चला रहा था और कुछ भी काम नहीं कर रहा था। तब मैंने पाया कि ग्रहण परियोजना सभी दुःख का कारण थी। मैं कमांड प्रॉम्प्ट से अपनी कक्षा चला गया, यह काम किया। एक नई ग्रहण परियोजना बनाई और वहां एक ही कोड चिपकाया, यह भी वहां काम किया। आपके समय और प्रयासों के लिए सभी लोगों को धन्यवाद।

0

मैंने एक साधारण NamespaceContext कार्यान्वयन (here) लिखा है, जो मदद की हो सकती है। यह इनपुट के रूप में Map<String, String> लेता है, जहां key एक उपसर्ग है, और value एक नामस्थान है।

यह NamespaceContext spesification का पालन करता है, और आप देख सकते हैं कि यह unit tests में कैसे काम करता है।

Map<String, String> mappings = new HashMap<>(); 
mappings.put("foo", "http://foo"); 
mappings.put("foo2", "http://foo"); 
mappings.put("bar", "http://bar"); 

context = new SimpleNamespaceContext(mappings); 

context.getNamespaceURI("foo"); // "http://foo" 
context.getPrefix("http://foo"); // "foo" or "foo2" 
context.getPrefixes("http://foo"); // ["foo", "foo2"] 

नोट यह Google Guava

संबंधित मुद्दे