Проверьте, существует ли 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
должно выполняться.