@ Алехандро предоставил лучший ответ XPath 1.0, который был известен годами с тех пор, как впервые использовался Джени Теннисон почти десять лет назад .
Единственный единственныйпроблема с этим выражением заключается в его блестящей элегантности, которая затрудняет понимание не только начинающим программистам.
В размещенном 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>