web-dev-qa-db-fra.com

Expression XSL/XPath pour vérifier si un nœud contient au moins un enfant non vide

Je dois vérifier si un nœud XML a au moins un enfant non vide. Appliquée à ce XML, l'expression devrait renvoyer true

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

J'ai essayé d'utiliser cette expression: <xsl:if test="not(/xml/node/child::* = '')"> mais il semble vérifier si all children ne sont pas vides.

Comment puis-je écrire une expression qui retourne true si au moins un élément n'est pas vide? Y a-t-il un moyen de faire cela sans créer un autre modèle pour itérer sur les enfants du nœud?

UPD: Je songe à compter les noeuds non vides comme
test="count(not(/xml/node/child::* = '')) &gt; '0'"
mais ne parvient pas à le faire fonctionner correctement. Cette expression n'est pas bien formée.

27
svz

Plus précis, plus simple et plus efficace (inutile d'utiliser la fonction count()) :

  /*/node/*[text()]

Si vous souhaitez exclure un élément contenant uniquement des enfants texte, utilisez:

  /*/node/*[normalize-space()]
33
Dimitre Novatchev

Vous avez juste besoin de <xsl:if test="/xml/node/* != ''" />.

Dans XPath, une comparaison = ou != où un côté est un ensemble de nœuds et l'autre une chaîne réussit si l'un des nœuds de l'ensemble réussit la comparaison. Ainsi

not(x = '')

signifie "il n'est pas vrai qu'un élément enfant x du nœud actuel ait une valeur de chaîne vide", ce qui est fondamentalement différent de

x != ''

ce qui signifie "au moins un élément enfant x du nœud actuel a une valeur de chaîne qui n'est pas vide". En particulier, si vous voulez vérifier que tousx enfants sont vides, vous devez utiliser un test "double négatif".

not(x != '')
11
Ian Roberts

Voici un XPath qui devrait accomplir le travail:

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

En cas d'utilisation dans un échantillon 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>

... qui, à son tour, est appliqué à l'exemple XML fourni:

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

... le résultat attendu est obtenu:

true

Si nous appliquons le même XSLT à un XML simplement modifié:

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

... encore une fois, le résultat attendu est obtenu:

false

Explication:

XPath utilisé recherche tous les enfants d'un élément <node> (qui sont, à leur tour, des enfants de l'élément racine) ayant une valeur de texte non vide (comme spécifié par text()); Si le nombre de ces enfants <node> est supérieur à 0, alors XPath est résolu en true.

4
ABach
<?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>

Explication Ceci trouvera le premier noeud avec une longueur de chaîne supérieure à zéro, puis comparera le contenu de ce noeud avec une chaîne vide (la comparaison renverra l'existence d'un noeud de chaîne non vide); Ce code peut également être utilisé pour rechercher un critère spécifique dans un nœud, par exemple, identifier l'existence d'un nœud contenant une chaîne spécifique ou commençant par un caractère ou une autre condition. veuillez utiliser ceci comme condition interne de la référence de noeud pour que le code fonctionne comme par magie.

0
HectorYep