2010-12-20 6 views
12

मैं एक्सएमएल दस्तावेजों की एक जोड़ी है कहो एक XPath (संस्करण 1.0 केवल) है कि के लिए "mystring" रिटर्नXPath डिफ़ॉल्ट मान वापस जाने के लिए अगर नोड मौजूद नहीं

<Foo> 
    <Bar/> 
    <Baz>mystring</Baz> 
</Foo> 

और

<Foo> 
    <Bar/> 
</Foo> 

मैं चाहता हूँ पहला दस्तावेज़ और दूसरे के लिए "नहीं मिला"। मैं

(string('not-found') | //Baz)[last()] 

कोशिश की, लेकिन संघ के बाएं हाथ की ओर एक नोड-सेट

उत्तर

16

XPath 1.0 में, उपयोग नहीं है:

concat(/Foo/Baz, 
     substring('not-found', 1 div not(/Foo/Baz))) 

आप को संभालने के लिए चाहते हैं सकारात्मक खाली Baz तत्व, उपयोग:

concat(/Foo/Baz, 
     substring('not-found', 1 div not(/Foo/Baz[node()]))) 

इस इनपुट के साथ:

<Foo> 
    <Baz/> 
</Foo> 

परिणाम: not-found स्ट्रिंग डेटा प्रकार।

+0

+1 अच्छा उत्तर। –

+0

चालाक; अच्छा काम-आसपास :) –

+1

यह वास्तव में अनजान XPath है, और जब मेरी असली दुनिया XPath को नोड को प्रतिस्थापित किया जाता है तो यह वास्तव में बदसूरत XPath भी है। लेकिन इसे आप को सौंपना है, यह वास्तव में चालाक है। –

1
/Foo/(Baz/string(), 'not-found')[1] 
+0

यह XPath के संस्करण 2 में काम करता है। संस्करण 1.0 में मुझे अप्रत्याशित टोकन मिलता है - ", 'नहीं मिला') [1]"। दुर्भाग्य से मुझे XPath 1.0 समाधान की आवश्यकता है। मैं इस –

+0

को प्रतिबिंबित करने के लिए प्रश्न संपादित करूँगा, खाली पाठ सामग्री के साथ नोड के लिए डिफ़ॉल्ट मान भी प्राप्त करने के लिए,/foo/(Baz/text(), 'नहीं मिला') [1] –

8

@ एलेजेंड्रो ने सर्वश्रेष्ठ XPath 1.0 उत्तर प्रदान किया, जो वर्षों से ज्ञात है, first used by Jeni Tennison लगभग दस साल पहले

इस अभिव्यक्ति के साथ एकमात्र समस्या इसकी चमकदार लालित्य है, जो न केवल नौसिखिया प्रोग्रामर द्वारा समझना मुश्किल बनाता है।

एक की मेजबानी की XPath 1.0 (और हर XPath होस्ट किया गया है!) एक और समझा जा सकता भाव उपयोग कर सकते हैं:

string((/Foo/Baz | $vDefaults[not(/Foo/Baz/text())]/Foo/Baz)[last()) 

यहाँ चर $vDefaults एक अलग दस्तावेज़ प्राथमिक XML के रूप में एक ही संरचना है कि है दस्तावेज़, और जिनके टेक्स्ट नोड्स में डिफ़ॉल्ट मान होते हैं।

या, यदि XSLT होस्टिंग भाषा है, एक document() समारोह उपयोग कर सकते हैं:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output method="text"/> 

<my:defaults> 
    <Foo> 
     <Bar/> 
     <Baz>not-found</Baz> 
    </Foo> 
</my:defaults> 

<xsl:template match="/"> 
    <xsl:value-of select= 
    "concat(/Foo/Baz, 
      document('')[not(current()/Foo/Baz/text())] 
             /*/my:defaults/Foo/Baz 
      )"/> 
</xsl:template> 
</xsl:stylesheet> 

या, concat() का उपयोग नहीं:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output method="text"/> 

<my:defaults> 
    <Foo> 
     <Bar/> 
     <Baz>not-found</Baz> 
    </Foo> 
</my:defaults> 

<xsl:variable name="vDefaults" select="document('')/*/my:defaults"/> 

<xsl:template match="/"> 
    <xsl:value-of select= 
    "(/Foo/Baz 
     | $vDefaults/Foo/Baz[not(current()/Foo/Baz/text())] 
     ) 
     [last()]"/> 
</xsl:template> 
</xsl:stylesheet> 
+1

+1 बेकर विधि के ऐतिहासिक संदर्भों के लिए देता है। –

+0

मेरे लिए कुछ भी आउटपुट नहीं करता है। –

+0

@Worse_Username, आपको एक अनुपालन XSLT 1.0 प्रोसेसर का उपयोग करने की आवश्यकता है - जिसे आप (कुछ भी निर्दिष्ट करने के लिए चूक गए?!?) का उपयोग नहीं कर रहे हैं। –

7

विशेष स्थिति: आप तो 0 अंक प्राप्त करना चाहते हैं यदि संख्यात्मक नोड गुम या खाली है, "sum (/ foo/baz)" फ़ंक्शन

का उपयोग करें
संबंधित मुद्दे