2010-02-12 14 views
12

Ich möchte ein Element zu einem XML-Dokument hinzufügen und ich möchte als Parameter den Pfad zu dem Element übergeben.Wie verwende ich einen Parameter in einem XSLT als XPath?

sample.xml Datei:

<?xml version="1.0"?> 
<stuff> 
    <element1> 
    <foo>2</foo> 
<bar/> 
    </element1> 
    <element2> 
<subelement/> 
<bar/> 
    </element2> 
    <element1> 
    <foo/> 
<bar/> 
    </element1> 
</stuff> 

Verwendung:

xalan.exe -p myparam "element1" sample.xml addelement.xslt 

würde ich folgendes Ergebnis erhalten:

<?xml version="1.0"?> 
<stuff> 
    <element1> 
    <foo>2</foo> 
    <bar/> 
    <addedElement/> 
    </element1> 
    <element2> 
<subelement/> 
<bar/> 
    </element2> 
    <element1> 
    <foo/> 
<bar/> 
    <addedElement/> 
    </element1> 
</stuff> 

ich addelement.xslt habe verwalten zu schreiben, Wenn ich den Pfad hartcodiere funktioniert es, aber wenn ich versuche, Parameter Myparam im Match-Attribut zu verwenden, bekomme ich:

XPathParserException: A node test was expected. 
pattern = '$myparam/*[last()]' Remaining tokens are: ('$' 'myparam' '/' '*' '[' 'last' '(' ')' ']') (addelement.xslt, line 12, column 42) 

addelement.xslt

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

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="element1/*[last()]"> 
    <xsl:copy-of select="."/> 
<addedElement></addedElement> 
</xsl:template> 

</xsl:stylesheet> 

addelement.xslt mit fest codierten Pfad ersetzt

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

<xsl:param name="myparam"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="$myparam/*[last()]"> 
    <xsl:copy-of select="."/> 
<addedElement></addedElement> 
</xsl:template> 

</xsl:stylesheet> 

Vielen Dank für

Antwort

6

mitzuhelfen Ich glaube nicht, dass Sie Variablen verwenden können/Paramater in passende Vorlagen, wie Sie sie codiert haben. Auch funktioniert das nicht

<xsl:template match="*[name()=$myparam]/*[last()]"> 

Stattdessen versuchen, die erste passende Vorlage zu ändern, um wie folgt, so dass die Parameterprüfung in dem Template-Code ist, nicht als Teil der Spiels Aussage.

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:if test="local-name() = $myparam"> 
      <addedElement/> 
     </xsl:if> 
    </xsl:copy> 
</xsl:template> 
+0

Haben Sie bedeuten, dass Variable/Parameter sind keine gültige XPath-Ausdruck? Ich kann jedoch nicht mit Ihrer Lösung arbeiten. – David

+3

Zunächst erlaubt XSLT 1.0 die Verwendung von Variablen/Parametern in Match-Mustern überhaupt nicht. XSLT 2.0 erlaubt es, aber wenn Sie Xalan, einen XSLT 1.0 Prozessor, verwenden, können Sie keine XSLT 2.0 Funktionen verwenden. Und zweitens, wenn Sie eine Variable oder einen Parameter vom Typ string mit einem Elementnamen haben, können Sie damit keine XPath-Ausdrücke dynamisch erstellen. So funktionieren Variable/Parameter nicht, weder in XPath noch in anderen Sprachen. Wenn der Wert der Variablen/Parameter vom Typ string ist, können Sie ihn an einer beliebigen Stelle verwenden, an der eine Zeichenfolge zulässig ist, wie es Tim getan hat. –

+0

Danke Martin, kennst du irgendwelche Kommandozeilen-basierten XSLT 2.0 Prozessoren? – David

1

Hier ist, wie Sie mit XSLT 1.0 tun könnte:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:param name="n" select="'element1'"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*/*[last()]"> 
    <xsl:choose> 
    <xsl:when test="local-name(..) = $n"> 
     <xsl:copy-of select="."/> 
     <addedElement></addedElement> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 
Verwandte Themen