Как использовать параметр в xslt в качестве XPath? - PullRequest
12 голосов
/ 12 февраля 2010

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

файл 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, когда он жестко запрограммирован, но когда я пытаюсь использовать Параметр 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>

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

Ответы [ 2 ]

6 голосов
/ 12 февраля 2010

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

<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>
1 голос
/ 12 февраля 2010

Вот как вы могли бы сделать это с 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>
...