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

XSL/XPath, чтобы проверить, содержит ли node хотя бы один непустой дочерний элемент

Мне нужно проверить, имеет ли XML node хотя бы один непустой дочерний элемент. Применительно к этому XML выражение должно возвращать true

<xml>
    <node>
       <node1/>
       <node2/>
       <node3>value</node3>
    </node>
</xml>

Я попытался использовать это выражение: <xsl:if test="not(/xml/node/child::* = '')">, но, похоже, проверяет, не являются ли все детьми.

Как написать выражение, которое возвращает true, если хотя бы один элемент не пуст? Есть ли способ сделать это без создания другого шаблона для итерации по node chldren?

UPD: Я думаю о подсчете непустых узлов, например, test="count(not(/xml/node/child::* = '')) &gt; '0'"
но как-то просто не может заставить его работать правильно. Это выражение не является корректным.

4b9b3361

Ответ 1

Более точный, более простой и эффективный (нет необходимости использовать функцию count()):

  /*/node/*[text()]

Если вы хотите исключить любой элемент, у которого есть только текстовые файлы только для пробелов, используйте:

  /*/node/*[normalize-space()]

Ответ 2

Вам просто нужно <xsl:if test="/xml/node/* != ''" />.

В сравнении XPath an = или !=, где одна сторона представляет собой набор node, а другая сторона - строка успешно, если любой из узлов в наборе проходит сравнение. Таким образом,

not(x = '')

означает "это не тот случай, когда дочерний элемент x текущего node имеет пустое строковое значение", которое принципиально отличается от

x != ''

что означает, что "хотя бы один дочерний элемент x текущего node имеет строковое значение, которое не пусто". В частности, если вы хотите проверить, что все x дети пустые, вам нужно использовать "двойной отрицательный" тест

not(x != '')

Ответ 3

Здесь один XPath, который должен выполнить задание:

count(/*/node/*[text()]) &gt; 0

При использовании в образце XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
     <xsl:value-of select="count(/*/node/*[text()]) &gt; 0" />
  </xsl:template>

</xsl:stylesheet>

... который, в свою очередь, применяется к предоставленному примеру XML:

<xml>
  <node>
    <node1/>
    <node2/>
    <node3>value</node3>
  </node>
</xml>

... создается ожидаемый результат:

true

Если мы применяем тот же XSLT к просто модифицированному XML:

<xml>
  <node>
    <node1/>
    <node2/>
    <node3/>
  </node>
</xml>

... снова получается ожидаемый результат:

false

Объяснение:

XPath использует поиск всех дочерних элементов <node> (которые, в свою очередь, являются дочерними элементами корневого элемента), которые имеют непустое текстовое значение (как указано text()); если число таких детей <node> больше 0, тогда XPath разрешается до true.

Ответ 4

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <xsl:value-of select="/*/node/*[string-length(text()) &gt;0]!=''"/>
    </xsl:template>
</xsl:stylesheet>

Объяснение Это найдет первый node с длиной строки больше нуля, а затем сравнивает содержимое node с пустой строкой (сравнение вернет существование непустой строки node); этот код также может быть использован для поиска конкретных критериев в любом node, например, для идентификации существования node, который содержит определенную строку или начинается с какого-либо символа или любого другого условия; используйте это как внутреннее условие ссылки node, чтобы код работал над своей магией.