Проверьте, существует ли узел с атрибутом равным значению - PullRequest
10 голосов
/ 07 декабря 2011

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

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

Кроме того, у меня есть узел с подузлами:

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

Теперь я хотел бы проверить, если узел сСуществует атрибут id, равный superid.

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

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

Ответы [ 4 ]

15 голосов
/ 07 декабря 2011

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

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
4 голосов
/ 07 декабря 2011

То, что у вас, похоже, работает для меня (.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 голосов
/ 07 декабря 2011

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

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

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

1 голос
/ 07 декабря 2011

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

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

  • Во-первых, смотрите эту часть спецификации XSLT (выделено мной):

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

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

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

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

    • набор узлов истинен тогда и только тогда, когда он непустой

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...