Проверьте, существует ли node с атрибутом equals value

У меня есть следующая переменная XSLT:

<xsl:variable name="superid" select="/contentdata/id"/>

Кроме того, у меня есть node с субномами:

<nodes>
    <node name="foo" id="bar" />
    <node name="john" id="doe" />
    <node name="jane" id="tarzan" />
</nodes>

Теперь я хочу проверить, существует ли node с атрибутом id, равным супераддию.

Я пробовал следующее (что явно не работает):

<xsl:if test="/nodes/node[@id = $superid]">Yes, Sir!</xsl:if>

Ответ 1

Использование

boolean(/nodes/node/@id = $superid)

Вот полное преобразование, показывающее это в действии:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vDoe" select="'doe'"/>
 <xsl:variable name="vXyz" select="'xyz'"/>

 <xsl:template match="/">
     id attribute with value "doe' exists: <xsl:text/>
     <xsl:value-of select="boolean(/nodes/node/@id = $vDoe)"/>
==========
     id attribute with value "xyz' exists: <xsl:text/>
     <xsl:value-of select="boolean(/nodes/node/@id = $vXyz)"/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к предоставленному XML-документу:

<nodes>
    <node name="foo" id="bar" />
    <node name="john" id="doe" />
    <node name="jane" id="tarzan" />
</nodes>

требуется, правильный результат получается:

     id attribute with value "doe' exists: true
==========
     id attribute with value "xyz' exists: false

Ответ 2

То, что у вас есть, работает для меня (.Net 3.5) - в соответствии с здесь.

Я попытался воссоздать ваш xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                >
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" />

    <xsl:template match="/xml">
        <xml>
            <xsl:apply-templates select="contentdata/id" />
        </xml>
    </xsl:template>

    <xsl:template match="id">
        <Result>
        <xsl:variable name="superid" select="."/>
        <SearchFor>
            <xsl:value-of select="$superid"/>
        </SearchFor>
        <IsPresent>
            <xsl:if test="/xml/nodes/node[@id = $superid]">Node is present</xsl:if>
        </IsPresent>
    </Result>
    </xsl:template>

</xsl:stylesheet>

Учитывая xml:

<xml>
    <contentdata>
        <id>doe</id>
        <id>unobtanium</id>
    </contentdata>
    <nodes>
        <node name='foo' id='bar' />
        <node name='john' id='doe' />
        <node name='jane' id='tarzan' />
    </nodes>
</xml>

Вывод:

<xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Result>
        <SearchFor>doe</SearchFor>
        <IsPresent>Node is present</IsPresent>
    </Result>
    <Result>
        <SearchFor>unobtanium</SearchFor>
        <IsPresent />
    </Result>
</xml>

Ответ 3

Если вы используете выражение xpath /nodes/node [@id = $superid]" > , тогда это будет поиск корня node из узлов в вашем XML-документе. Однако в вашем вопросе вы, кажется, подразумеваете, что узлы - это всего лишь node внутри вашего документа, не обязательно корневой элемент. Попробуйте это вместо

<xsl:if test="//nodes/node[@id = $superid]">Yes, Sir!</xsl:if>

Двойной слэш выбирает узлы в документе везде, где они находятся в иерархии, а не только верхний уровень node.

Ответ 4

Это должно работать так, как вы ожидаете. Одно из ваших выражений (либо в переменной select, либо в атрибуте test) не должно выбирать то, что вы думаете. (Вы не предоставили свой полный вход, поэтому вам трудно помочь.)

Обратите внимание на несколько вещей о xsl:if:

  • Сначала см. эту часть спецификации XSLT (выделение мое собственное):

    Элемент xsl: if имеет атрибут test, который указывает выражение. Содержимое - это шаблон. Выражение оценивается и результирующий объект преобразуется в логическое, как если бы по вызову boolean function. Если результат верен, тогда шаблон содержимого инстанцирован в противном случае ничего не создается.

  • Итак, как будет работать вызов функции boolean на вашем входе? См. эту часть спецификации XPath (опять же, мое внимание):

    Булева функция преобразует свой аргумент в логическое значение следующим образом:

    • число истинно тогда и только тогда, когда оно не является ни положительным, ни отрицательным нулем, ни NaN

    • a node -set является истинным тогда и только тогда, когда он не пуст

    • строка истинна тогда и только тогда, когда ее длина отлична от нуля

    • объект типа, отличного от четырех основных типов, преобразуется в логическое значение, которое зависит от этого типа

Итак, если /contentdata/id действительно выбирает id, для которого /nodes/node[@id = $superid] возвращает непустой node -set, тогда тело xsl:if должно выполняться.