XPath

2009-05-21 14 views
9

में पहला परिणाम का चयन करें मैं इस सवाल को देखा है: Select first instance only with XPath?XPath

लेकिन अगर मैं एक नोड-सेट इस तरह है:


<container value=""> 
    <data id="1"></data> 
    <data id="2">test</data> 
    <container> 
    <data id="1">test</data> 
    <data id="3">test</data> 
    </container> 
</container> 

अब मेरी परिदृश्य है इस नोड सेट गहरा है कि एक दस्तावेज़ के अंदर, और मेरे पास आंतरिक कंटेनर के लिए एक सूचक है। इसलिए मुझे अपने XPath को "/ कंटेनर/कंटेनर" के साथ उपसर्ग करना है (पथ वास्तव में लंबा है, लेकिन इस उदाहरण के लिए यह करना चाहिए)।

संपादित करें: जो मैं चाहता हूं वह 1 की आईडी के साथ "डेटा" नोड है, जो सबसे कम नोड पहले या निकटतम पूर्वजों से आना चाहिए। इसलिए, अगर मैं इसे "वर्तमान" (/ कंटेनर/कंटेनर) पर नहीं ढूंढ पा रहा हूं तो मुझे पूर्वजों को देखना चाहिए और निकटतम एक प्राप्त करना चाहिए (या अंत में, कुछ भी नहीं मिला)। मैं इस की कोशिश की है:

/कंटेनर/कंटेनर/पूर्वज या स्वयं :: कंटेनर/डेटा [@ id = "1"]

कौन सा वापस एक परिणाम के दो नोड्स के साथ सेट लाता है। मैंने सोचा कि मैं गहराई पाने के लिए आखिरी() का उपयोग कर सकता हूं, इसलिए मैंने अंत में इसका सामना किया, लेकिन इसका कोई फायदा नहीं हुआ।

+0

विनिर्देश अधिक स्पष्टता के साथ कर सकता है। आप डेटा नोड चाहते हैं? डेटा नोड में 1 की आईडी होनी चाहिए? मूल कंटेनर को फॉर्म करें यदि डेटा नोड में 1 की आईडी नहीं है, तो आप दस्तावेज़ को मूल कंटेनर में ले जाना चाहते हैं ताकि यह देखने के लिए कि उसके पास डेटा आईडी नोड 1 है, यदि आईडी के साथ डेटा नोड तक नहीं चल रहा है 1 में पाया गया है। क्या यह इसका वर्णन करता है? – AnthonyWJones

+0

मैंने वर्णन करने की कोशिश की कि मैं थोड़ा स्पष्ट क्यों खोज रहा था, हालांकि कुछ ने अनुमान लगाया था। माफ़ कीजिये! –

उत्तर

5

कैसे आप पिछले() पर टैकिंग कोशिश की थी? मुझे लगता है कि यह काम करना चाहिए:

/container/container/ancestor-or-self::container/data[@id="1"][last()] 

संपादित करें:

ठीक है, निश्चित रूप से, मैं भूल गया कोष्ठकों:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

कौन सा यह एक ही बनाता है अन्य उत्तर में से एक के रूप में; हालांकि, के रूप में मूल रूप से पोस्ट बताते हैं, इस अभिव्यक्ति पर विफल रहता है:

<container value=""> 
    <container> 
    <data id="1">a3</data> 
    <data id="3">a4</data> 
    </container> 
    <data id="1">a1</data> 
    <data id="2">a2</data> 
</container> 

stackoverflow की भावना के सच है, मैं फिर भी मेरा उत्तर अन्य उत्तर में से एक के साथ गठबंधन और कुछ है कि सभी मामलों में काम करता है प्राप्त कर सकते हैं:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"] 

वैसे, देखते हैं यदि एक से अधिक @ आईडी-है-1 < डेटा> एक कंटेनर के बच्चों, इस सब के सब वापस आ जाएगी।केवल इस तरह की पहली < डेटा> तत्व लौटने के लिए:

position() == 1 
+0

यदि वांछित परिणाम पर मेरा पढ़ना सही है (बड़ा अगर) यह काम नहीं करेगा क्योंकि आखिरी() पूर्वजों या स्वयं की दोनों शाखाओं से मेल खाएगा - यही वह है वास्तविक समस्या, इसलिए आपको परिणाम सेट को जल्दी से (जैसा कि मेरे पास है) या देर से क्लिप करना होगा (जैसे डेव करता है)। – annakata

+0

यह एक करता है। बहुत बहुत धन्यवाद (हर कोई भी)! –

1

मैं तुम्हारे लिए क्या पूछ रहे हैं पर 100% स्पष्ट नहीं कर रहा हूँ, लेकिन अगर मैं यह सही पढ़ा हो सकता है आप बस चाहते हैं:

/container/container/ancestor-or-self::container[1]/data[@id='1'] 

टिप्पणी "[1]"

संपादित करें: इसके बारे में सोचा थोड़ा और और नीचे सभी मामलों के लिए मेरे लिए काम करता अब तक @ आईडी के लिए वहीं देख = $ एन

/container/container/ancestor-or-self::container[data[@id=$N]][1]/data[@id=$N] 

सुंदर चरम xpathing। असल में क्या हो रहा है कि पूर्वजों या स्वयं से नोडसेट स्थिति 1 पर सबसे कम क्रम देता है - यही वह है जिसे आप चाहते हैं - लेकिन आपको उस पर दूसरी शर्त लगाने की आवश्यकता है कि नोड में आपके पास रुचि रखने वाला डेटा नोड भी है, एक बार जब आप उन शर्तों को पूरा कर लेंगे तो आपके पास सही नोड होगा, अब आप वास्तविक डेटा में आगे बढ़ना चाहते हैं।

99 समय xpath का% यदि आप एक एल्गोरिथ्म :) के रूप में अलग ले और यह के बारे में सोच आसान हो जाता है

+0

मैंने कोशिश की, लेकिन इसमें हर मामले को शामिल नहीं किया गया है। अगर मैं @ id = '2' के बजाय देख रहा हूं तो क्या होगा? मैं पूर्वजों से पहले वर्तमान नोड के परिणामों का पक्ष लेना चाहता हूं, लेकिन फॉलबैक करने में सक्षम हूं। –

+0

संपादित करें: मेरा मानना ​​है कि सभी सूचीबद्ध मामलों को शामिल किया गया है – annakata

0

बजाय

@id="1" 

आप की कोशिश की है। प्रयास करें:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

इसी तरह:

//container[last()] 

और:

(//container)[last()] 

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

+0

यदि स्थिति() == 1 काम करेगी तो बस पूर्वजों या स्वयं को छोड़कर :: सभी को एक साथ छोड़ दें। मुझे लगता है कि आवश्यकता केवल किसी भी पहले डेटा नोड के लिए नहीं है बल्कि 1 आईडी की एक आईडी नोड है। प्रश्न उतना स्पष्ट नहीं है जितना हो सकता है। – AnthonyWJones

11

यकीन last() सही ढंग से दायरे वाला बनाओ:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1] 
+0

आह, यह काम किया! धन्यवाद। –

+0

दरअसल, मैंने पाया कि यह इस मामले में काम नहीं करता है कि बच्चे के कंटेनर नोड को मिलान डेटा तत्व से पहले निर्दिष्ट किया गया है। –

+0

@ निक स्पेस - मैंने नीचे दिए गए मेरे उत्तर में सुधार किया है, और अब यह उस कोने के मामले को भी कवर करता है –

0

कोशिश [स्थिति() = 1]

पूर्व।

/कंटेनर/कंटेनर/पूर्वज या स्वयं :: कंटेनर/डेटा [स्थिति() = 1]