XPath में (टेक्स्ट), 'कुछ स्ट्रिंग') एक से अधिक टेक्स्ट सबनोड के साथ नोड के साथ उपयोग किए जाने पर काम नहीं करता है


258

मैं Xpath के साथ dom4j के साथ एक छोटी सी समस्या है ...

कहते हैं कि मेरा XML है

<Home>
    <Addr>
        <Street>ABC</Street>
        <Number>5</Number>
        <Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
    </Addr>
</Home>

आइए बताते हैं कि मैं उन सभी नोड्स को ढूंढना चाहता हूं जो मूल तत्व दिए गए पाठ में एबीसी हैं ...

तो मुझे जो xpath लिखना होगा वो होगा

//*[contains(text(),'ABC')]

हालाँकि ऐसा नहीं है कि DOM4j की वापसी क्या है .... क्या यह एक डोम 4j समस्या है या मेरी समझ है कि xpath कैसे काम करता है। चूँकि वह क्वेरी केवल स्ट्रीट एलिमेंट को लौटाती है न कि कमेंट एलिमेंट को।

DOM टिप्पणी तत्व को चार टैग दो के साथ एक संयुक्त तत्व बनाता है

[Text = 'XYZ'][BR][BR][Text = 'ABC'] 

मुझे लगता है कि क्वेरी को अभी भी तत्व को वापस करना चाहिए क्योंकि यह तत्व ढूंढना चाहिए और उस पर रन होना चाहिए, लेकिन यह नहीं है ... ...

निम्नलिखित क्वेरी तत्व को वापस कर देती है, लेकिन यह कहीं अधिक वापस लौटता है, बस तत्व, यह मूल तत्वों को भी लौटाता है ... जो समस्या के लिए अवांछनीय है ...

//*[contains(text(),'ABC')]

क्या कोई भी xpath क्वेरी जानता है जो सिर्फ तत्वों को वापस करेगा <Street/>और <Comment/>?


जहाँ तक मैं बता सकता हूँ, //*[contains(text(),'ABC')]केवल <Street>तत्व देता है। यह <Street>या के किसी भी पूर्वजों को वापस नहीं करता है <Comment>
केन ब्लूम

जवाबों:


706

<Comment>टैग दो पाठ नोड्स और दो शामिल <br>बच्चों के रूप में नोड्स।

आपकी xpath अभिव्यक्ति थी

//*[contains(text(),'ABC')]

इसे तोड़ने के लिए,

  1. * एक चयनकर्ता है जो किसी भी तत्व (यानी टैग) से मेल खाता है - यह एक नोड-सेट लौटाता है।
  2. []एक सशर्त उस नोड सेट में प्रत्येक व्यक्ति के नोड पर चल रही हैं। यह मेल खाता है यदि कोई भी अलग-अलग नोड्स जो इसे संचालित करता है तो कोष्ठक के अंदर की स्थितियों से मेल खाता है।
  3. text()एक चयनकर्ता है जो सभी पाठ नोड्स से मेल खाता है जो संदर्भ नोड के बच्चे हैं - यह एक नोड सेट लौटाता है।
  4. containsएक फ़ंक्शन है जो एक स्ट्रिंग पर संचालित होता है। यदि इसे एक नोड सेट पास किया जाता है, तो नोड सेट को नोड के स्ट्रिंग-मान को नोड-सेट में बदलकर एक स्ट्रिंग में बदल दिया जाता है जो दस्तावेज़ क्रम में पहली बार होता है । इसलिए, यह आपके <Comment>तत्व में केवल पहले पाठ नोड से मेल खा सकता है - अर्थात् BLAH BLAH BLAH। चूंकि यह मेल नहीं खाता है, आप <Comment>अपने परिणामों में नहीं मिलता है ।

आपको इसे बदलने की आवश्यकता है

//*[text()[contains(.,'ABC')]]
  1. * एक चयनकर्ता है जो किसी भी तत्व (यानी टैग) से मेल खाता है - यह एक नोड-सेट लौटाता है।
  2. बाहरी []एक सशर्त है जो उस नोड सेट में प्रत्येक व्यक्ति नोड पर संचालित होता है - यहां यह दस्तावेज़ में प्रत्येक तत्व पर संचालित होता है।
  3. text() एक है चयनकर्ता है जो सभी पाठ नोड्स से मेल खाता है जो संदर्भ नोड के बच्चे हैं - यह एक नोड सेट लौटाता है।
  4. भीतरी [] एक सशर्त है जो उस नोड सेट में प्रत्येक नोड पर संचालित होता है - यहां प्रत्येक व्यक्तिगत पाठ नोड। प्रत्येक व्यक्तिगत पाठ नोड कोष्ठक में किसी भी पथ के लिए प्रारंभिक बिंदु है, और इसे स्पष्ट रूप .से कोष्ठक के भीतर भी संदर्भित किया जा सकता है । यह मेल खाता है अगर किसी भी व्यक्तिगत नोड्स को संचालित करता है तो यह कोष्ठक के अंदर की स्थितियों से मेल खाता है।
  5. containsएक फ़ंक्शन है जो एक स्ट्रिंग पर संचालित होता है। यहाँ यह एक अलग-अलग टेक्स्ट नोड ( .) है। चूंकि यह <Comment>व्यक्तिगत रूप से टैग में दूसरा टेक्स्ट नोड पारित किया गया है , यह 'ABC'स्ट्रिंग को देखेगा और इसे मिलान करने में सक्षम होगा।

1
बहुत बढ़िया im एक xpath noob का एक छोटा सा है, इसलिए मुझे यह प्राप्त करने दें, पाठ () एक ऐसा फ़ंक्शन है जिसमें अभिव्यक्ति शामिल है (, 'एबीसी'), क्या कोई मौका है जो आप समझा सकते हैं इसलिए मैं इस तरह से नहीं करता हूं बेवकूफ सामान फिर;)
माइक मिल्किन

28
मैंने एक लंबी व्याख्या प्रदान करने के लिए अपना उत्तर संपादित किया है। मैं वास्तव में खुद XPath के बारे में इतना कुछ नहीं जानता - मैंने तब तक थोड़ा प्रयोग किया जब तक कि मैं उस संयोजन पर ठोकर नहीं खा गया। एक बार जब मेरे पास काम करने का संयोजन था, तो मैंने अनुमान लगाया कि क्या चल रहा था और एक्सपीथ मानक में देखा कि मैं क्या सोच रहा था और इस पर स्पष्टीकरण लिखूंगा।
केन ब्लूम

2
आप इस मामले को असंवेदनशील खोज कैसे बनाएंगे?
ज़ैक

@Zack: कृपया इसे एक नया प्रश्न बनाएं।
user1129682

1
मुझे पता है कि यह एक पुराना धागा है, लेकिन क्या कोई इस बात पर टिप्पणी कर सकता है कि क्या मौलिक अंतर है, अधिमानतः केन ब्लूम द्वारा दिए गए उत्तर के बीच कुछ सरल परीक्षण मामलों के साथ //*[contains(., 'ABC')]। मैंने हमेशा माइक मिल्किन द्वारा दिए गए पैटर्न का उपयोग किया था, यह सोचते हुए कि यह अधिक उपयुक्त था, लेकिन containsवर्तमान संदर्भ में ऐसा करना वास्तव में ऐसा लगता है जो मैं अधिक बार चाहता हूं।
नाइटिकम

7

[contains(text(),'')]केवल सही या गलत लौटाता है। यह कोई तत्व परिणाम नहीं लौटाएगा।


यह काम नहीं करेगा अगर मेरे पास '' या '' है तो हम कैसे ट्रिम कर सकते हैं?
शरीफ

contains(text(),'JB-')काम नहीं है! तर्क के रूप में दो तारconatains लेता है - ! पाठ () स्ट्रिंग नहीं है , एक फ़ंक्शन है! contains(**string**, **string**)
अताचिहादो

6

XML दस्तावेज़:

<Home>
    <Addr>
        <Street>ABC</Street>
        <Number>5</Number>
        <Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
    </Addr>
</Home>

XPath अभिव्यक्ति:

//*[contains(text(), 'ABC')]

//*रूट नोड के किसी भी मूल तत्व से मेल खाता है । वह है, कोई भी तत्व लेकिन मूल नोड।

[...]एक विधेय है , यह नोड-सेट को फ़िल्टर करता है। इसके लिए नोड्स लौटाता ...है true:

एक नया नोड-सेट बनाने के लिए एक विधेय नोड-सेट [...] को फ़िल्टर करता है। फ़िल्टर किए जाने वाले नोड-सेट में प्रत्येक नोड के लिए, PredicateExpr का मूल्यांकन किया जाता है [...]; यदि PredicateExpr उस नोड के लिए सही का मूल्यांकन करता है, तो नोड को नए नोड-सेट में शामिल किया जाता है; अन्यथा, यह शामिल नहीं है।

contains('haystack', 'needle')रिटर्न trueअगर haystack शामिल हैं needle :

बूलियन होता है (स्ट्रिंग, स्ट्रिंग)

यदि फ़ंक्शन में सत्यता होती है यदि पहला तर्क स्ट्रिंग में दूसरा तर्क स्ट्रिंग है, और अन्यथा गलत रिटर्न देता है।

लेकिन contains()इसके पहले पैरामीटर के रूप में एक स्ट्रिंग लेता है। और यह नोड्स पारित किया है। इससे निपटने के लिए कि पहले पैरामीटर के रूप में प्रत्येक नोड या नोड-सेट को फ़ंक्शन द्वारा स्ट्रिंग में बदल दिया जाता है string():

एक तर्क को स्ट्रिंग में परिवर्तित किया जाता है जैसे कि स्ट्रिंग फ़ंक्शन को कॉल करके।

string()पहले नोडstring-value का फ़ंक्शन रिटर्न :

नोड-सेट एक नोड में स्ट्रिंग नोड में परिवर्तित करके नोड-सेट में लौटाया जाता है जो पहले दस्तावेज़ क्रम में होता है। यदि नोड-सेट खाली है, तो एक खाली स्ट्रिंग लौटा दी जाती है।

string-valueएक तत्व नोड का :

तत्व नोड का स्ट्रिंग-मान दस्तावेज़ क्रम में तत्व नोड के सभी पाठ नोड वंश के स्ट्रिंग-मानों का संघनन है।

string-valueएक पाठ नोड का :

किसी टेक्स्ट नोड का स्ट्रिंग-मान वर्ण डेटा है।

तो, मूल रूप string-valueसे सभी पाठ हैं जो एक नोड में समाहित हैं (सभी वंशज पाठ नोड्स का संघनन)।

text() एक नोड परीक्षण है जो किसी भी पाठ नोड से मेल खाता है:

नोड टेस्ट टेक्स्ट () किसी भी टेक्स्ट नोड के लिए सही है। उदाहरण के लिए, बच्चा :: टेक्स्ट () संदर्भ नोड के टेक्स्ट नोड बच्चों का चयन करेगा।

कहा जाने के बाद, //*[contains(text(), 'ABC')]किसी भी तत्व (लेकिन रूट नोड) से मेल खाता है, जिसमें पहला पाठ नोड होता है ABC। चूंकि text()एक नोड-सेट देता है जिसमें संदर्भ नोड के सभी बाल पाठ नोड्स होते हैं (एक अभिव्यक्ति का मूल्यांकन किया जाता है)। लेकिन contains()पहले वाला ही लेता है। तो पथ के ऊपर दस्तावेज़ के लिए Streetतत्व से मेल खाता है ।

निम्न अभिव्यक्ति //*[text()[contains(., 'ABC')]]किसी भी तत्व (लेकिन रूट नोड) से मेल खाती है, जिसमें कम से कम एक बाल पाठ नोड है, जिसमें शामिल है ABC.संदर्भ नोड का प्रतिनिधित्व करता है। इस मामले में, यह किसी भी तत्व का मूल पाठ नोड लेकिन रूट नोड है। इसलिए पथ के ऊपर दस्तावेज़ के लिए मेल खाता है Street, औरComment तत्वों से ।

अब फिर, //*[contains(., 'ABC')]किसी भी तत्व (लेकिन रूट नोड) से मेल खाता है , जिसमें ABC(वंश पाठ नोड्स के संघात में) शामिल है। दस्तावेज़ के ऊपर से मेल खाता है के लिए Home, Addr, Street, और Commentतत्वों। जैसे, //*[contains(., 'BLAH ABC')]से मेल खाता है Home, Addrऔर Commentतत्वों।


0

यह मुझे थोड़ा समय लगा लेकिन आखिरकार समझ में आया। कस्टम xpath जिसमें कुछ पाठ शामिल हैं, मेरे लिए पूरी तरह से काम करता है।

//a[contains(text(),'JB-')]

2
contains(text(),'JB-')काम नहीं है! तर्क के रूप में दो तारconatains लेता है - ! पाठ () स्ट्रिंग नहीं है , एक फ़ंक्शन है! contains(**string**, **string**)
अताचिहादो

0

स्वीकृत उत्तर सभी मूल नोड्स को भी लौटा देगा। स्ट्रिंग के बाद भी एबीसी के साथ केवल वास्तविक नोड्स प्राप्त करने के लिए
:

//*[text()[contains(.,'ABC')]]/text()[contains(.,"ABC")]

0
//*[text()='ABC'] 

रिटर्न

<street>ABC</street>
<comment>BLAH BLAH BLAH <br><br>ABC</comment>

3
पांच मौजूदा उत्तरों के साथ एक नौ साल पुराने प्रश्न के उत्तर को जोड़ते समय यह बताना बहुत महत्वपूर्ण है कि आपके उत्तर के प्रश्न के अद्वितीय नए पहलू क्या हैं।
जेसन एलर

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