2011-01-06 10 views
30

इस Stack Overflow answer में कल्पना करें कि आपको एक विशेष तालिका और उसके बाद की सभी पंक्तियों को चुनने की आवश्यकता है। एचटीएमएल का अनुमोदन करने के कारण, निम्न में से सभी तीन कानूनी मार्कअप हैं:पदानुक्रम में वैकल्पिक तत्व के साथ XPath

<table id="foo"><tr>...</tr></table> 
<table id="foo"><tbody><tr>...</tr></tbody></table> 
<table id="foo"><tr>...</tr><tbody><tr>...</tr></tbody></table> 

आप टेबल में नेस्ट टेबल के बारे में चिंतित हैं, और इसलिए की तरह
table[@id="foo"]//tr एक XPath का उपयोग नहीं करना चाहते हैं।

आप एक regex के रूप में अपने वांछित XPath निर्दिष्ट कर सकते हैं, तो यह कुछ ऐसा दिखाई दे सकता है:
table[@id="foo"](/tbody)?/tr

सामान्य तौर पर, कैसे आप एक XPath अभिव्यक्ति है कि एक चयनकर्ता के पदानुक्रम में एक वैकल्पिक तत्व की अनुमति देता है निर्दिष्ट कर सकते हैं?

स्पष्ट होने के लिए, मैं वास्तविक दुनिया की समस्या को हल करने या किसी विशिष्ट दस्तावेज़ के विशिष्ट तत्व का चयन करने की कोशिश नहीं कर रहा हूं। मैं समस्याओं की एक वर्ग को हल करने के लिए तकनीकों के लिए पूछ रहा हूँ।

+0

ओह, और सादगी और व्यापकता की खातिर' tfoot' HTML में कानूनी तत्वों। – Phrogz

उत्तर

19

मैं नहीं दिख रहा है तुम क्यों उपयोग नहीं कर सकते यह:

//table[@id='foo']/tr|//table[@id='foo']/tbody/tr 

आप नोड सेट गठबंधन के बिना एक अभिव्यक्ति चाहते हैं:

//tr[(.|parent::tbody)[1]/parent::table[@id='foo']] 
+0

आपका पहला जवाब डिमिट्रे सुझाव दे रहा था। मैंने आपकी दूसरी अभिव्यक्ति के लिए स्वीकृति बदल दी है, हालांकि, यह अधिक DRY है। – Phrogz

+1

@Phrogz: THis अभिव्यक्ति में पिछड़ा धुरी होता है और एक अभिव्यक्ति से कम कुशल होता है जिसमें केवल आगे अक्ष होती है। "DRY" -ness के लिए, आप एक अभिव्यक्ति की समझदारी पर भी विचार करना चाहेंगे, जो निश्चित रूप से इसकी रखरखाव के साथ जुड़ा हुआ है। :) –

+0

@Dimitre धन्यवाद आप दक्षता पर अपनी टिप्पणी के लिए। आप सही हैं कि सरल विकल्प (आपका उत्तर और इस उत्तर में पहली अभिव्यक्ति) को समझना आसान है, भले ही यह गलतियों को संपादित करने और बनाए रखने के लिए कठिन हो। – Phrogz

7

उपयोग:

//table[@id="foo"]/*[self::tbody or self::thead or self::tfoot]/tr 
    | 
    //table[@id="foo"]/tr 

किसी भी tr तत्व है कि किसी भी table एक id विशेषता "foo" या किसी tr तत्व है कि एक tbody का एक बच्चा एक बच्चा है वह यह है कि है कि का एक बच्चा है का चयन करें कोई table

+0

मैं इस क्षेत्र में आपकी विशेषज्ञता की सराहना करता हूं, लेकिन क्या यह वास्तव में सबसे अच्छा किया जा सकता है? यदि एक्सपैथ के पहले और आखिरी हिस्से सिर्फ "टेबल" और "tr" हैं तो यह बहुत बुरा नहीं है, लेकिन 'div [@ id = "content] // table [@ class =" comments "] जैसे कुछ के साथ (/ tbody)?/tr/[td // text() [शामिल है (।, 'targetString')]] 'यह बहुत गैर- [DRY] बन जाता है (http://en.wikipedia.org/wiki/Don't_repeat_yourself) एक भिन्नता के चारों ओर अभिव्यक्ति को डुप्लिकेट करने के लिए। – Phrogz

+0

@Phrogz: नहीं, यह मेरी प्रारंभिक अभिव्यक्ति के रूप में लगभग सरल है - संपादन देखें। यह XPath 2.0 के साथ और अधिक सुरुचिपूर्ण हो सकता है और साथ ही साथ XML दस्तावेज़ के साथ भी अधिक सुरुचिपूर्ण हो सकता है एक ज्ञात एक्सएमएल स्कीमा (जो एक्सएचटीएमएल के साथ मामला है) –

+0

अधिक सुरुचिपूर्ण XPath 2.0 संस्करण क्या है? सबसे अच्छा मैं समझ सकता था कि एक कदम वैकल्पिक था "।"और वैकल्पिक भाग। टीईआई पर सैक्सन के साथ, यह मेरे लिए काम करता है: /TEI.2/text/(.|group/text)/body/div1 –

3

XPath 2.0 में, वैकल्पिक कदम हो सकता है (tbody|.) के रूप में व्यक्त किया गया।

//table[@id="foo"]/(tbody|.)/tr 

XPathTester.com demo

पाइप (|) को दर्शाता है union (दोनों में से नोड सेट), dot (.) पहचान कदम (सिर्फ लौटने क्या पिछले चरण में किया था) को दर्शाता है।

यह एक बार में एक से अधिक वैकल्पिक तत्वों को शामिल करने विस्तारित किया जा सकता: मैं `thead` अनदेखी और कर रहा हूँ

//table[@id="foo"]/(thead|tbody|tfoot|.)/tr 
+0

होने वाला है, मुझे यकीन नहीं है कि यह XPath 1.0 में क्यों काम नहीं करता है। ऐसा लगता है कि ऐसा होना चाहिए, क्योंकि '(tbody |।)' मान्य 'FilterExpr' टोकन ('PrimaryExpr' →' '(' expr ')'' → 'OrExpr' → 'ANDExpr' →' समानता एक्स्प्र '→' RelationalExpr' जैसा दिखता है '→ 'AdditiveExpr' →' गुणक एक्स्प्र '→' UnaryExpr' → 'UnionExpr')। – Palec

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