2010-02-12 19 views
12

Me gustaría agregar un elemento a un documento xml y me gustaría pasar como parámetro la ruta al elemento. archivo¿Cómo usar un parámetro en xslt como XPath?

sample.xml:

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

Usando:

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

me gustaría el siguiente resultado:

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

he logran escribir addelement.xslt, cuando codigo duro la ruta funciona, pero cuando trato de usar el parámetro myparam en el atributo de coincidencia que obtengo:

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 con la ruta codificada reemplazado

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

Gracias por ayudar

Respuesta

6

No creo que se pueden utilizar variables en/Paramaters haciendo coincidir las plantillas como usted ha codificado. Incluso esto no funciona

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

En su lugar, trate de cambiar la primera plantilla a juego para la siguiente manera, de modo que la verificación de los parámetros está dentro del código de la plantilla, no como parte de la declaración partido.

<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

¿Quiere decir que variables/parámetros no son una expresión XPath válida? Sin embargo, no puedo hacer que funcione con su solución. – David

+3

En primer lugar, XSLT 1.0 no permite el uso de variables/parámetros en los patrones de coincidencia en absoluto. XSLT 2.0 lo permite, pero si usa Xalan, un procesador XSLT 1.0, no puede usar las características XSLT 2.0. Y en segundo lugar, si tiene una variable o parámetro de tipo cadena con un nombre de elemento, entonces no puede usarlo para construir expresiones XPath de forma dinámica. No es así como funcionan los parámetros/variables, ni en XPath ni en otros lenguajes. Si el valor de variable/parámetro es de tipo cadena, puede usarlo en cualquier lugar donde se permita una cadena, como lo ha hecho Tim. –

+0

Gracias Martin, ¿conoces algún procesador XSLT 2.0 basado en línea de comandos? – David

1

Aquí es cómo se puede hacer eso con XSLT 1.0:

<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> 
Cuestiones relacionadas