说我有一对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字符串数据类型.
@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)