如果节点不存在,则XPath返回默认值

Pau*_*zie 15 xpath

说我有一对XML文档

<Foo>
    <Bar/>
    <Baz>mystring</Baz>
</Foo>
Run Code Online (Sandbox Code Playgroud)

<Foo>
    <Bar/>
</Foo>
Run Code Online (Sandbox Code Playgroud)

我想要一个XPath(仅限1.0版),它为第一个文档返回"mystring",为第二个文档返回"not-found".我试过了

(string('not-found') | //Baz)[last()]
Run Code Online (Sandbox Code Playgroud)

但联盟的左侧不是节点集

小智 17

在XPath 1.0中,使用:

concat(/Foo/Baz,
       substring('not-found', 1 div not(/Foo/Baz)))
Run Code Online (Sandbox Code Playgroud)

如果要处理posible空Baz元素,请使用:

concat(/Foo/Baz,
       substring('not-found', 1 div not(/Foo/Baz[node()])))
Run Code Online (Sandbox Code Playgroud)

有了这个输入:

<Foo>
    <Baz/>
</Foo>
Run Code Online (Sandbox Code Playgroud)

结果:not-found字符串数据类型.

  • 也许这对大多数人来说是显而易见的,但是`div`是除法,而不是html div标签.把它放在那里.:) (7认同)

Nis*_*shi 14

特殊情况:如果想要在数字节点丢失或为空时获得0,请使用"sum(/ Foo/Baz)"函数


Dim*_*hev 8

@Alejandro提供了最好的XPath 1.0答案,这个答案已经有多年了,自从大约十年前Jeni Tennison首次使用以来.

这个表达式的唯一问题是它的闪亮优雅,这使得不仅新手程序员难以理解.

在托管的XPath 1.0中(每个XPath都托管!),可以使用更易理解的表达式:

string((/Foo/Baz | $vDefaults[not(/Foo/Baz/text())]/Foo/Baz)[last())
Run Code Online (Sandbox Code Playgroud)

此处变量$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>
Run Code Online (Sandbox Code Playgroud)

或者,不使用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>
Run Code Online (Sandbox Code Playgroud)


Max*_*oro 5

/Foo/(Baz/string(), 'not-found')[1]
Run Code Online (Sandbox Code Playgroud)