कई टैग का चयन करने के लिए XPath


132

इस सरलीकृत डेटा प्रारूप को देखते हुए:

<a>
    <b>
        <c>C1</c>
        <d>D1</d>
        <e>E1</e>
        <f>don't select this one</f>
    </b>
    <b>
        <c>C2</c>
        <d>D2</d>
        <e>E1</e>
        <g>don't select me</g>
    </b>
    <c>not this one</c>
    <d>nor this one</d>
    <e>definitely not this one</e>
</a>

आप सभी Cs, Ds और Es का चयन कैसे करेंगे जो Bतत्वों के बच्चे हैं?

मूल रूप से, कुछ इस तरह:

a/b/(c|d|e)

अपने ही स्थिति है, बस के बजाय में a/b/, क्वेरी उन का चयन करने के लिए अग्रणी C, D, Eनोड्स वास्तव में काफी जटिल है, इसलिए मैं यह कर रहा से बचने के लिए करना चाहते हैं:

a/b/c|a/b/d|a/b/e

क्या यह संभव है?

जवाबों:


207

एक सही उत्तर है :

/a/b/*[self::c or self::d or self::e]

ध्यान दें कि यह

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

बहुत लंबा और गलत दोनों है । यह XPath अभिव्यक्ति नोड्स का चयन करेगी:

OhMy:c

NotWanted:d 

QuiteDifferent:e

2
'या' प्रत्येक के लिए काम नहीं करता है, आपको इसके बजाय एक ऊर्ध्वाधर रेखा का उपयोग करने की आवश्यकता होगी। '
गुआस्केनो

8
@ गुआस्केनो, orएक तार्किक ऑपरेटर है - यह दो बूलियन मूल्यों पर काम करता है। XPath यूनियन ऑपरेटर |नोड्स के दो सेटों पर काम करता है। ये काफी अलग हैं और उनमें से प्रत्येक के लिए विशिष्ट उपयोग के मामले हैं। उपयोग करने से मूल समस्या | को हल किया जा सकता है, लेकिन यह XPath अभिव्यक्ति को समझने के लिए एक लंबे और अधिक जटिल और चुनौतीपूर्ण परिणाम देता है। इस उत्तर में सरल अभिव्यक्ति, जो orऑपरेटर का उपयोग करके वांछित नोड-सेट का उत्पादन करता है और एक एक्सएसएलटी ऑपरेशन के "चयन" विशेषता में निर्दिष्ट किया जा सकता है <xsl:for-each>। कर के देखो।
दिमित्रे नोवत्चेव

4
@JonathanBenn, जो कोई भी "नामस्थान की परवाह नहीं करता है" वास्तव में XML के बारे में परवाह नहीं करता है, और XML का उपयोग नहीं करता है। के उपयोग के local-name()नाम स्थान तत्व में है की केवल सही अगर हम यह है कि स्थानीय नाम के साथ सभी तत्वों का चयन करना चाहते है, भले ही यह एक बहुत ही दुर्लभ मामला है - आम लोगों में अंतर के बारे में देखभाल करते हैं:। kitchen:tableऔर sql:table, या के बीच architecture:column, sql:column, array:column,military:column
Dimitre Novatchev

3
@DimitreNovatchev आप एक अच्छा बिंदु बनाते हैं। मैं HTML निरीक्षण के लिए XPath का उपयोग कर रहा हूं, जो एक किनारे का मामला है जहां नाम स्थान इतना महत्वपूर्ण नहीं है ...
जोनाथन बेन्

2
वह सुपर है। तुम कहाँ से आए?
कीथ टायलर

46

आप इसके बजाय विशेषता परीक्षण के साथ पुनरावृत्ति से बच सकते हैं:

a/b/*[local-name()='c' or local-name()='d' or local-name()='e']

दिमित्रे की विरोधी राय के विपरीत, ऊपर एक वैक्यूम में गलत नहीं है जहां ओपी ने नामस्थान के साथ बातचीत को निर्दिष्ट नहीं किया है। self::अक्ष नाम स्थान सीमित है, local-name()नहीं है। अगर ओपी का इरादा कब्जा करने का हैc|d|e नेमस्पेस की परवाह किए बिना करना है (जो कि मैं सुझाव दूंगा कि समस्या की प्रकृति को देखते हुए एक संभावित परिदृश्य है) तो यह "एक और जवाब है कि अभी भी कुछ सकारात्मक वोट हैं" जो गलत है।

आप परिभाषा के बिना निश्चित नहीं हो सकते हैं, हालांकि मैं अपने उत्तर को गलत तरीके से हटाने के लिए बहुत खुश हूं क्योंकि यदि ओपी अपने प्रश्न को स्पष्ट करता है कि मैं गलत हूं।


3
यहां 3rd पार्टी के रूप में बोलते हुए - व्यक्तिगत रूप से, मुझे लगता है कि दिमित्रे के सुझाव को उन मामलों को छोड़कर बेहतर अभ्यास किया जा सकता है जहां उपयोगकर्ता के पास नामस्थान के अप्रासंगिक टैग के बारे में स्पष्ट (और अच्छा) कारण है; अगर किसी ने यह एक दस्तावेज़ के खिलाफ किया, जिसे मैं अलग-अलग नाम की सामग्री में मिला रहा था (संभवतः एक अलग टूलकिन द्वारा पढ़ने का इरादा था), तो मैं उनके व्यवहार को बहुत अनुचित समझूंगा। उस ने कहा, तर्क है - जैसा कि आप सुझाव देते हैं - थोड़ा असहनीय।
चार्ल्स डफी

4
ठीक वही जो मेरे द्वारा खोजा जा रहा था। XML वास्तविक जीवन में जिस तरह से उपयोग किए जाते हैं, वह एक अपवित्र गड़बड़ है। कमी के लिए कुछ निर्दिष्ट करने में सक्षम होने के लिए जैसे / a / b / ( : c | : d | * e) आपका समाधान वही है जिसकी आवश्यकता है। Purist वे सभी चाहते हैं जो बहस कर सकते हैं, लेकिन उपयोगकर्ताओं को परवाह नहीं है कि ऐप टूट जाता है क्योंकि जो कुछ भी उनकी इनपुट फ़ाइल ने नाम स्थान को खराब कर दिया। वे चाहते हैं कि यह काम करे।
घोस्ट्रेडर

7
मुझे केवल इतना ही अंदाजा है कि इन दोनों उत्तरों में क्या अंतर होगा और किसी ने भी समझाने की जहमत नहीं उठाई। "नेमस्पेस प्रतिबंधक" का क्या अर्थ है? अगर मैं उपयोग local-name()करता हूं , तो क्या इसका मतलब है कि यह किसी भी नामस्थान के साथ टैग से मेल खाएगा? यदि मैं उपयोग करता हूं self::, तो उसे किस नाम स्थान से मेल खाना होगा? मैं केवल कैसे मेल करूंगा OhMy:c?
मेसट्रस

15

क्यों नहीं a/b/(c|d|e)? मैंने सिर्फ सैक्सन एक्सएमएल लाइब्रेरी (कुछ क्लोजर अच्छाई के साथ अच्छी तरह से लिपटा हुआ) की कोशिश की, और यह काम करने लगता है। abc.xmlओपी द्वारा वर्णित डॉक्टर है।

(require '[saxon :as xml])
(def abc-doc (xml/compile-xml (slurp "abc.xml")))
(xml/query "a/b/(c|d|e)" abc-doc)
=> (#<XdmNode <c>C1</c>>
    #<XdmNode <d>D1</d>>
    #<XdmNode <e>E1</e>>
    #<XdmNode <c>C2</c>>
    #<XdmNode <d>D2</d>>
    #<XdmNode <e>E1</e>>)

8
हां, लेकिन वह XPath 2.0 है

इसने मेरे लिए अच्छा काम किया। ऐसा लगता है XPath 2.0 पायथन 2. पर lxml में HTML पार्स के लिए डिफ़ॉल्ट है
मार्टिन Burch

-1

यकीन नहीं होता कि यह मदद करता है, लेकिन XSL के साथ, मैं कुछ ऐसा करूंगा:

<xsl:for-each select="a/b">
    <xsl:value-of select="c"/>
    <xsl:value-of select="d"/>
    <xsl:value-of select="e"/>
</xsl:for-each>

और यह XPath B नोड के सभी बच्चों का चयन नहीं करेगा:

a/b/*

धन्यवाद केल्विन, लेकिन मैं एक्सएसएल का उपयोग नहीं कर रहा हूं, और वास्तव में बी के नीचे अधिक तत्व हैं जो मैं चयन नहीं करना चाहता हूं। मैं अपने उदाहरण को स्पष्ट करने के लिए अपडेट करूंगा।
निकेल

ओह, अच्छी तरह से उस मामले में annakata के पास समाधान है।
केल्विन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.