2010-02-12 6 views
12

Я хотел бы добавить элемент в XML-документ, и я хотел бы передать в качестве параметра путь к элементу.Как использовать параметр в xslt как XPath?

sample.xml файл:

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

Использование:

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

Я хотел бы следующий результат:

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

Я успел написать addelement.xslt, когда hardcoding путь он работает, но когда я пытаюсь использовать параметр myparam в атрибуте match, я получаю:

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 с закодированным путем заменен

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

Спасибо за помощь

ответ

6

Я не думаю, что вы можете использовать переменные/PARAMATERS в соответствующие шаблоны, как вы закодировали. Даже это не работает

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

Вместо этого попробуйте изменить первый шаблон соответствия как следует, так что проверка параметров внутри кода шаблона, а не как часть заявления матча.

<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

ли вы имеете в виду, что переменные/параметры не являются допустимым выражением XPath? Однако я не могу заставить его работать с вашим решением. – David

+3

Прежде всего, XSLT 1.0 не позволяет использовать переменные/параметры в шаблонах совпадений вообще. XSLT 2.0 действительно позволяет, но если вы используете Xalt, процессор XSLT 1.0, вы не можете использовать функции XSLT 2.0. И, во-вторых, если у вас есть переменная или параметр строки типа с именем элемента, вы не можете использовать ее для динамического создания выражений XPath. Это не то, как переменные/параметры работают, ни в XPath, ни на других языках. Если значение переменной/параметра имеет строку типа, вы можете использовать его в любом месте, где разрешена строка, как это сделал Тим. –

+0

Спасибо, Мартин, вы знаете какой-нибудь процессор XSLT 2.0 с командной строкой? – David

1

Вот как вы могли бы сделать это с помощью 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> 
Смежные вопросы