2009-05-27 15 views
12

के साथ नेमस्पेस का उपयोग करना जावा में नेमस्पेस को शामिल करने वाले xpath को हल करने के लिए NamespaceContext ऑब्जेक्ट के उपयोग की आवश्यकता होती है, यूआरएल नेमस्पेस के उपसर्ग और इसके विपरीत। हालांकि, मुझे इसे लागू करने के अलावा NamespaceContext प्राप्त करने के लिए कोई तंत्र नहीं मिल सकता है। यह काउंटर-अंतर्ज्ञानी लगता है।नेमस्पेस कॉन्टेक्स्ट और XPath

प्रश्न: वहाँ एक दस्तावेज़ से एक NamespaceContext प्राप्त करने के लिए, या एक, या कि, उपसर्गों को पूरी तरह छोड़ और पूरी तरह से योग्य नाम के साथ xpath निर्दिष्ट करने में नाकाम रहने बनाने के लिए किसी भी आसान तरीका है?

+1

आपके प्रश्न से कुछ बुनियादी मिसंडरोड है: आप एक्सपीआई के साथ एक्सएमआई से सभी नामस्थान यूआरआई प्राप्त कर सकते हैं (एसओ में इसके लिए उत्तर हैं), लेकिन आप एक उपसर्ग-नामस्थान यूआरआई बाइंडिंग क्लास को सरल नहीं बना सकते हैं क्योंकि * * प्रत्येक नोड के लिए ** यह एक अलग बाध्य हो सकता है। नोड्स का चयन करते समय आपको अपने वांछित तत्वों के नामों को पहले से जानना चाहिए ** और इसमें उनके नेमस्पेस यूआरआई ** –

उत्तर

11

नेमस्पेस कॉन्टेक्स्ट उदाहरण प्राप्त करना संभव है अपनी कक्षा के बिना। इसका class-use पृष्ठ दिखाता है कि आप javax.xml.stream पैकेज का उपयोग करके एक प्राप्त कर सकते हैं।

String ctxtTemplate = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" />"; 
NamespaceContext nsContext = null; 

XMLInputFactory factory = XMLInputFactory.newInstance(); 
XMLEventReader evtReader = factory 
    .createXMLEventReader(new StringReader(ctxtTemplate)); 
while (evtReader.hasNext()) { 
    XMLEvent event = evtReader.nextEvent(); 
    if (event.isStartElement()) { 
    nsContext = ((StartElement) event) 
     .getNamespaceContext(); 
    break; 
    } 
} 

System.out.println(nsContext.getNamespaceURI("")); 
System.out.println(nsContext.getNamespaceURI("foo")); 
System.out.println(nsContext 
    .getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE)); 
System.out.println(nsContext 
    .getNamespaceURI(XMLConstants.XML_NS_PREFIX)); 

forgoing उपसर्गों पूरी तरह अस्पष्ट भाव होने की संभावना है - अगर आप नामस्थान उपसर्ग ड्रॉप करना चाहते हैं, आप दस्तावेज़ प्रारूप को बदलने की जरूरत होगी। किसी दस्तावेज़ से संदर्भ बनाना आवश्यक नहीं है। उपसर्गों इस कोड के रूप में, XPath अभिव्यक्ति में प्रयोग किया जाता हैं, किसी भी दस्तावेज़ में नहीं लोगों से मेल करने के लिए है:

String xml = "<data xmlns=\"http://base\" xmlns:foo=\"http://foo\" >" 
    + "<foo:value>" 
    + "hello" 
    + "</foo:value>" 
    + "</data>"; 
String expression = "/stack:data/overflow:value"; 
class BaseFooContext implements NamespaceContext { 
    @Override 
    public String getNamespaceURI(String prefix) { 
    if ("stack".equals(prefix)) 
     return "http://base"; 
    if ("overflow".equals(prefix)) 
     return "http://foo"; 
    throw new IllegalArgumentException(prefix); 
    } 

    @Override 
    public String getPrefix(String namespaceURI) { 
    throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Iterator<String> getPrefixes(
     String namespaceURI) { 
    throw new UnsupportedOperationException(); 
    } 
} 
XPathFactory factory = XPathFactory.newInstance(); 
XPath xpath = factory.newXPath(); 
xpath.setNamespaceContext(new BaseFooContext()); 
String value = xpath.evaluate(expression, 
    new InputSource(new StringReader(xml))); 
System.out.println(value); 

न तो कार्यान्वयन StAX एपीआई और न ही ऊपर एक करके लौटे पूर्ण class/method लागू दस्तावेज़ में परिभाषित अनुबंध। आप एक पूर्ण, मानचित्र-आधारित कार्यान्वयन here प्राप्त कर सकते हैं।

+0

शामिल हैं, इस तरह के मेरे डर की पुष्टि करता है। मेरे पास नेमस्पेस कॉन्टेक्स्ट नहीं हो सकता है जो मनमाने ढंग से मैपिंग करता है जब तक कि मैं कक्षा को स्वयं लागू नहीं करता। लेकिन XML स्ट्रीम उदाहरण कम से कम मुझे एक स्थिर फ़ंक्शन से नेमस्पेस कॉन्टेक्स्ट बनाने का पथ देता है जो आपके द्वारा पहले उदाहरण में एक माइक्रो दस्तावेज़ बनाता है। मैं कोशिश करूँगा। – Jherico

+0

हां, यह दर्द का एक सा है कि कोई डिफ़ॉल्ट कार्यान्वयन नहीं है। – McDowell

+0

मैं सबमिट करता हूं कि वह बेवकूफ है। सार्वजनिक एपीआई में उपयोग किए जाने वाले अन्य जावा इंटरफेस में सार्वजनिक रूप से उपलब्ध ठोस कार्यान्वयन या कारखानों का कोई सार्वजनिक रूप से उपलब्ध नहीं है? – Jherico

7

मैं अभी xpath और नेमस्पेस कॉन्टेक्सट्स का उपयोग करके काम कर रहा हूं। मैं on developerworks मुद्दे के अच्छे इलाज में आया था।

+2

आईबीएम से इस निबंध को पढ़ने के बाद, मैं समझ सकता हूं कि डिफ़ॉल्ट कार्यान्वयन क्यों नहीं है। इस समस्या को हल करने के कई तरीके हैं। उस ने कहा: अपाचे जैसे ओपन सोर्स समूह क्यों नहीं, विभिन्न कार्यान्वयन की लाइब्रेरी बनाते हैं? – kevinarpe

6

मुझे "Apache WebServices Common Utilities" नामक एक सुविधाजनक कार्यान्वयन मिला, जिसे नेमस्पेस कॉन्टेक्स्ट आईएमपीएल कहा जाता है।

आप इस कक्षा प्राप्त करने के लिए निम्नलिखित Maven निर्भरता का उपयोग कर सकते हैं:

<dependency> 
    <groupId>org.apache.ws.commons</groupId> 
    <artifactId>ws-commons-util</artifactId> 
    <version>1.0.1</version> 
</dependency> 

मैं निम्नलिखित तरीके से इसका इस्तेमाल किया है (मैं जानता हूँ कि अपनी सैक्स के लिए बनाया गया है, लेकिन कोड, ठीक है पढ़ने के बाद):

NamespaceContextImpl nsContext = new NamespaceContextImpl(); 
nsContext.startPrefixMapping("foo", "my.name.space.com"); 

आपको एंडपेफिक्स मैपिंग कहने की आवश्यकता नहीं है।

+1

आप अभी भी नामस्थानों को हार्डकोड कर रहे हैं! – Meitham

+0

बिल्कुल वही जो मैं खोज रहा था। जावाडोक: http://ws.apache.org/commons/util/apidocs/index.html –

+0

मीथम - मैं ऐसा कोई तरीका नहीं है जो नाम स्थान को हार्डकोडिंग से बचाता है। आप इस नेमस्पेस संदर्भ को बनाकर XPath खोज को बूटस्ट्रैप कर रहे हैं, इसे प्रत्येक नामस्थान में एक छोटा उपसर्ग मैप करके प्रारंभ करना * आपको पता है * दस्तावेज़ में निहित है, और फिर XPath द्वारा खोजते समय आप पथ को परिभाषित करते समय उन उपसर्गों का उपयोग करते हैं। –

1

आप स्प्रिंग ढांचे आप अपने NamespaceContext कार्यान्वयन org.springframework.util.xml.SimpleNamespaceContext

यह आसफ Mesika से एक की तरह एक ऐसी ही जवाब है पुन: उपयोग कर सकते हैं का उपयोग कर रहे हैं। इसलिए यह आपको अपने दस्तावेज़ के आधार पर स्वचालित रूप से नेमस्पेस कॉन्टेक्स्ट नहीं देता है। आपको इसे स्वयं बनाना है। फिर भी यह आपकी मदद करता है क्योंकि यह आपको कम से कम शुरू करने के लिए एक कार्यान्वयन देता है।

जब हमें इसी तरह की समस्या का सामना करना पड़ा, वसंत SimpleNamespaceContext और "अपाचे वेब सर्विसेज कॉमन यूटिलिटीज" दोनों काम करते थे। हम अपाचे वेब सर्विसेज कॉमन यूटिलिटीज पर अतिरिक्त जार निर्भरता से बचना चाहते थे और स्प्रिंग वन का इस्तेमाल करते थे, क्योंकि हमारा आवेदन स्प्रिंग आधारित है।

0

आप Jersey 2 का उपयोग कर रहे हैं और केवल एक डिफ़ॉल्ट XML नामस्थान (xmlns="...") है, तो आप SimpleNamespaceResolver उपयोग कर सकते हैं:

<?xml version="1.0" encoding="UTF-8"?> 
<Outer xmlns="http://host/namespace"> 
    <Inner /> 
</Outer> 
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 
docBuilderFactory.setNamespaceAware(true); 
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 

Document document = docBuilder.parse(new File("document.xml")); 
String query = "/t:Outer/t:Inner"; 

XPath xpath = XPathFactory.newInstance().newXPath(); 
String xmlns = document.getDocumentElement().getAttribute("xmlns"); 
xpath.setNamespaceContext(new SimpleNamespaceResolver("t", xmlns)); 

NodeList nodeList = (NodeList) xpath.evaluate(query, document, XPathConstants.NODESET); 

//nodeList will contain the <Inner> element 

तुम भी xmlns मैन्युअल अगर आप चाहते हैं निर्दिष्ट कर सकते हैं।

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