2010-12-20 123 views
12

說我有一對XML文檔的的XPath返回默認值,如果節點不存在

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

<Foo> 
    <Bar/> 
</Foo> 

我想返回「MyString的」爲一個XPath(版本1.0只)第一份文件和第二份「未找到」。我試圖

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

但工會的左手邊是不是一個節點集

回答

16

在XPath 1.0,使用:如果你要處理的

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

posible empty Baz元素,用途:

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

利用該輸入:

<Foo> 
    <Baz/> 
</Foo> 

結果:not-found字符串數據類型。

+0

+1好答案。 – 2010-12-20 15:01:47

+0

聰明;良好的解決方法:) – 2010-12-20 15:11:23

+1

這是一個非常不直觀的XPath,當我的真實世界XPath節點被替換時,它也是一個非常難看的XPath。但要把它交給你,這真的很聰明。 – 2010-12-20 15:41:51

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

這適用於XPath的第2版。在版本1.0中,我收到意外的令牌 - 「,'未找到')[1]」。不幸的是我需要一個XPath 1.0解決方案。我將編輯該問題以反映此問題 – 2010-12-20 13:47:37

+0

要爲具有空文本內容的節點生成默認值,請使用:/ Foo /(Baz/text(),'not-found')[1] – 2015-08-05 17:41:47

8

@Alejandro提供了最好的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對於貝克爾方法的歷史參考。 – 2010-12-20 16:31:05

+0

不輸出任何東西給我。 – 2017-09-20 08:09:43

+0

@ Worse_Username,你需要使用一個兼容的XSLT 1.0處理器 - 你(沒有指定任何東西?!?)沒有使用。 – 2017-09-20 13:39:58

7

特殊情況: 如果您如果數字節點缺失或爲空,想要得到0,使用「sum(/ Foo/Baz)」函數

相關問題