wake-up-neo.com

XSL / XPath-Ausdruck, um zu überprüfen, ob ein Knoten mindestens ein nicht leeres untergeordnetes Element enthält

Ich muss überprüfen, ob ein XML-Knoten mindestens ein nicht leeres untergeordnetes Element hat. Auf dieses XML angewendet, sollte der Ausdruck true zurückgeben.

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

Ich habe versucht, diesen Ausdruck zu verwenden: <xsl:if test="not(/xml/node/child::* = '')">, aber es scheint zu prüfen, ob alle Kinder nicht leer sind.

Wie kann ich einen Ausdruck schreiben, der true zurückgibt, wenn mindestens ein Element nicht leer ist? Gibt es eine Möglichkeit, dies zu tun, ohne eine weitere Vorlage zu erstellen, die über Knotenklassen iteriert?

PD: Ich denke an das Zählen von nicht leeren Knoten wie
test="count(not(/xml/node/child::* = '')) &gt; '0'"
aber irgendwie kann es einfach nicht richtig funktionieren. Dieser Ausdruck ist nicht gut geformt.

27
svz

genauer, einfacher und effizienter (keine Verwendung der Funktion count()) :

  /*/node/*[text()]

Wenn Sie ein Element ausschließen möchten, das nur aus Whitespace-Text bestehende untergeordnete Elemente enthält, verwenden Sie:

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

Sie brauchen nur <xsl:if test="/xml/node/* != ''" />.

In XPath ist ein =- oder !=-Vergleich möglich, bei dem eine Seite eine Knotengruppe und die andere Seite eine Zeichenfolge ist, wenn any der Knoten in der Gruppe den Vergleich bestehen. Somit

not(x = '')

bedeutet "es ist nicht der Fall, dass ein x child-Element des aktuellen Knotens einen leeren String-Wert hat", was sich grundlegend von dem unterscheidet

x != ''

was bedeutet "mindestens ein x untergeordnetes Element des aktuellen Knotens hat einen nicht leeren String-Wert". Wenn Sie insbesondere überprüfen möchten, ob all x leer sind, müssen Sie einen "doppelt negativen" Test verwenden

not(x != '')
11
Ian Roberts

Hier ist ein XPath, der die Aufgabe erfüllen sollte:

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

Bei Verwendung in einem Beispiel-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>

... was wiederum auf die bereitgestellte Beispiel-XML angewendet wird:

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

... das erwartete Ergebnis wird erzeugt:

true

Wenn wir dasselbe XSLT auf ein einfach modifiziertes XML anwenden:

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

... wieder wird das erwartete Ergebnis erzielt:

false

Erklärung:

Der verwendete XPath sucht nach allen untergeordneten Elementen eines <node>-Elements (die wiederum untergeordnete Elemente des Stammelements sind), die einen nicht leeren Textwert haben (wie von text() angegeben). Wenn die Anzahl solcher <node>-Kinder größer als 0 ist, wird der XPath in true aufgelöst.

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>

Erläuterung Dadurch wird der erste Knoten mit einer Zeichenfolgenlänge größer als Null gefunden und dieser Knoteninhalt dann mit einer leeren Zeichenfolge verglichen (der Vergleich gibt das Vorhandensein eines nicht leeren Zeichenfolgeknotens zurück). Dieser Code kann auch verwendet werden, um in einem Knoten nach bestimmten Kriterien zu suchen, z. B. das Vorhandensein eines Knotens zu identifizieren, der eine bestimmte Zeichenfolge enthält oder mit einem Zeichen oder einer anderen Bedingung beginnt. Verwenden Sie dies als innere Bedingung der Knotenreferenz, damit der Code seine Magie entfalten kann.

0
HectorYep