Подтвердить что ты не робот

XPath возвращает значение по умолчанию, если node нет

Скажем, у меня есть пара XML-документов

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

и

<Foo>
    <Bar/>
</Foo>

Мне нужен XPath (только версия 1.0), который возвращает "mystring" для первого документа и "не найден" для второго. Я попробовал

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

но левая сторона объединения не является node -set

4b9b3361

Ответ 1

В 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 строковый тип данных.

Ответ 2

@Alejandro предоставил лучший ответ XPath 1.0, который был известен годами, поскольку впервые использовавшийся 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>

Ответ 3

Специальный случай: Если вы хотите получить 0, если числовое число node отсутствует или пустое, используйте функцию "sum (/Foo/Baz)"

Ответ 4

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