11 Stimmen

xsl:apply-template nur auf Knoten mit bestimmten Attributwerten

Ich habe ein XML-Dokument, das ich einer XSLT unterziehe. Die Struktur ist etwa so:

<root>
  <item value="1">
     <object/>
  </item>
  <item value="2" />
     <object/>
  </item>
</root>

Mein Ziel ist es, am Ende eine transformierte XML zu haben, die ähnlich ist:

<root>
 <parent>
  <object-one value-one="1"/>
 </parent>
 <parent>
  <object-two value-two="2"/>
 </parent>
</root>

Mein XSLT ist ähnlich wie:

<xsl:apply-templates select="object" />

<xsl:template match="object">
    <xsl:call-template name="1" />
    <xsl:call-template name="2" />
</xsl:template>

<xsl:template name="1" match="object[item/@value = '1'">
  <xsl:element name="object-one" namespace="http://something.org">
    <xsl:attribute name="_Description">
      <xsl:value-of select="@_Type"/>
    </xsl:attribute>
    <xsl:attribute name="_Type">
      <xsl:value-of select="@_Amount"/>
   </xsl:attribute>
  </xsl:element>
</xsl:template>

 <xsl:template name="2" match="object[item/@value = '2'">
  <xsl:element name="object-two" namespace="http://something.org">
    <xsl:attribute name="OriginalAmount">
      <xsl:value-of select="@_Amount"/>
    </xsl:attribute>
  </xsl:element>
</xsl:template>

Das Problem ist, dass auf alle Elementknoten dieselbe Vorlage angewendet wird. Wie kann ich eine Vorlage nur auf bestimmte Knoten anwenden?

9voto

EDIT : Jetzt für verschiedene Eingabebeispiele (korrigiert für wohlgeformt):

<root>
    <item value="1">
        <object/>
    </item>
    <item value="2" >
        <object/>
    </item>
</root>

Dieses Stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:num="number" extension-element-prefixes="num">
    <num:num>one</num:num>
    <num:num>two</num:num>
    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item">
        <parent>
            <xsl:apply-templates/>
        </parent>
    </xsl:template>
    <xsl:template match="object">
        <xsl:variable name="vTextNumber" select="document('')/*/num:*[number(current()/../@value)]"/>
        <xsl:element name="object-{$vTextNumber}">
            <xsl:attribute name="value-{$vTextNumber}">
                <xsl:value-of select="../@value"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Ausgabe:

<root>
    <parent>
        <object-one value-one="1" />
    </parent>
    <parent>
        <object-two value-two="2" />
    </parent>
</root>

EDIT 2 : Was ist nun in Ihrem Stylesheet-Fragment falsch? Nun, es sieht so aus, als wüssten Sie nicht, wie der Prozessor die Anwendung von Template-Regeln auflöst, auch XPath-Navegation.

Erstens, diese object[item/@value = '1'] passt nur auf diese Art der Eingabe

<object>
    <item value="1"/>
</object>

Zweitens: Beachten Sie diese drei Regeln

1 -

<xsl:template match="object">
</xsl:template> 

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 

Mit Ihrer letzten Eingabe, zunächst object Element (in der Reihenfolge des Dokuments) den Regeln 1 und 2 entsprechen, und der Prozessor würde dann beschließen, Regel 2 anzuwenden. Und warum? Von http://www.w3.org/TR/xslt#conflict

Als nächstes werden alle übereinstimmenden Vorlagenregeln, die eine niedrigere Priorität haben als die passende Schablonenregel oder Regeln mit der höchsten Priorität werden aus der Berücksichtigung. Die Priorität einer Vorlageregel wird durch den Parameter Prioritätsattribut der Vorlage Regel festgelegt. Der Wert dieses Attributs muss eine reelle Zahl (positiv oder negativ) sein, entsprechend der Produktionsnummer mit einem optionalem führenden Minuszeichen (-). Die Standardpriorität wird wie folgt errechnet wie folgt:

  • Wenn das Muster mehrere Alternativen enthält, die durch | getrennt sind, wird es
    gleichwertig mit einer Reihe von Schablonenregeln behandelt wird, eine für jede
    alternativ.
  • Wenn das Muster die Form eines QNamens hat, dem ein
    ChildOrAttributeAxisSpecifier oder hat die Form processing-instruction(Literal)
    ein ChildOrAttributeAxisSpecifier vorangestellt ist, dann ist die Priorität 0.
  • Wenn das Muster die Form NCName:* hat, dem ein
    ChildOrAttributeAxisSpecifier, so beträgt die Priorität -0,25.
  • Andernfalls, wenn das Muster nur aus einem NodeTest besteht besteht, dem ein ChildOrAttributeAxisSpecifier vorangestellt ist, dann beträgt die Priorität -0,5.
  • Andernfalls beträgt die Priorität 0,5.

0voto

Rob Fonseca-Ensor Punkte 15345

Vielleicht können Sie Ihre Übereinstimmungen präzisieren:

<xsl:template name="item1" match="item[@value=1]">
    <xsl:element name="item" namespace="http://something.org">
        <xsl:attribute name="_Description">
            <xsl:value-of select="@_Type"/>
        </xsl:attribute>
        <xsl:attribute name="_Type">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

<xsl:template name="item2" match="item[@value=2]">
    <xsl:element name="item2_item" namespace="http://something.org">
        <xsl:attribute name="OriginalAmount">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

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