18 Stimmen

XPath-Ausdruck zur Auswahl aller XML-Kinderknoten außer einer bestimmten Liste?

Hier sind die Beispieldaten:

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
                <customField1>Whatever</customField1>
                <customField2>Whatever</customField2>
                <customField3>Whatever</customField3>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
                <customField1>Whatever</customField1>
                <customField2>Whatever</customField2>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
                <customField1>Whatever</customField1>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
</catalog>

Angenommen, ich möchte alles außer den Elementen Preis und Jahr auswählen. Ich würde erwarten, dass ich etwas wie das Folgende schreibe, was natürlich nicht funktioniert.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <xsl:for-each select="//cd/* except (//cd/price|//cd/year)">
    Current node: <xsl:value-of select="current()"/>
    <br />
  </xsl:for-each>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Bitte helfen Sie mir, eine Möglichkeit zu finden, bestimmte untergeordnete Elemente auszuschließen.

40voto

Tomalak Punkte 320467
<xsl:for-each select="//cd/*[not(self::price or self::year)]">

Aber eigentlich ist das schlecht und unnötig kompliziert. Besser:

<xsl:template match="catalog">
  <html>
    <body>
      <xsl:apply-templates select="cd/*" />
    </body>
  </html>
</xsl:template>

<!-- this is an empty template to mute any unwanted elements -->
<xsl:template match="cd/price | cd/year" />

<!-- this is to output wanted elements -->
<xsl:template match="cd/*">
  <xsl:text>Current node: </xsl:text>
  <xsl:value-of select="."/>
  <br />
</xsl:template>

Vermeiden Sie <xsl:for-each> . Fast immer ist es das falsche Werkzeug und sollte ersetzt werden durch <xsl:apply-templates> y <xsl:template> .

Dies funktioniert aufgrund der Spezifität des übereinstimmenden Ausdrucks. match="cd/price | cd/year" ist spezifischer als match="cd/*" und ist daher die bevorzugte Vorlage für cd/price o cd/year Elemente. Versuchen Sie nicht, Knoten auszuschließen, lassen Sie sie kommen und behandeln Sie sie, indem Sie sie verwerfen.

9voto

ndim Punkte 33229

Ich würde mit etwas experimentieren wie

"//cd/*[(name() != 'price') and (name() != 'year')]"

Oder Sie machen einen normalen rekursiven Vorlagenabgleich mit <xsl:apply-templates/> und haben dann leere Vorlagen für <price/> y <year/> Elemente:

<xsl:template match="price"/>
<xsl:template match="year"/>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X