XSLT: контекст XPath и документ () - PullRequest
3 голосов
/ 16 декабря 2011

У меня XSLT вот так:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                         xmlns:xalan="http://xml.apache.org/xalan">

  <xsl:variable name="fooDocument" select="document('fooDocument.xml')"/>

  <xsl:template match="/">
    <xsl:apply-templates select="$fooDocument//*"/>
  </xsl:template>

  <xsl:template match="nodeInFooDocument">
    <xsl:variable name="valueFromSource" select="//someSourceElement"/>
  </xsl:template>
</xsl:transform>

Во втором шаблоне, который соответствует узлам в fooDocument.xml, который загружен document(), я хочу получить доступ к узлам в источнике XML, на котором выполняется преобразование. Это не работает с //someSourceElement, потому что, очевидно, XPath выполняет этот путь в контексте fooDocument.

Первое, что приходит на ум, это:

...
<!-- global variable -->
<xsl:variable name="root" select="/"/>

...
<!-- in the template -->
<xsl:variable name="valueFromSource" select="$root//someSourceElement"/>

...

Но я не могу использовать этот обходной путь, потому что фактически моя переменная выбрана следующим образом:

<xsl:variable name="valueFromSource" select="xalan:evaluate($someXPathString)"/>

$someXPathString не создается в файле XSLT, но загружается из fooDocument (и содержит абсолютный путь, подобный тому, который использовался выше). Тем не менее, мне нужно как-то изменить контекст XPath обратно на источник XML. очень хакерский обходной путь, который я нашел, это:

<xsl:for-each select="$root[1]">
  <xsl:variable name="valueFromSource" select="xalan:evaluate($someXPathString)"/>
</xsl:for-each>

(бесполезный) цикл for-each изменяет контекст обратно на основной источник XML, таким образом XPath оценивает правильно. Но очевидно, что это не приемлемое решение.

Есть ли способ сделать это правильно , или кто-то может предложить лучший обходной путь?

Ответы [ 2 ]

3 голосов
/ 16 декабря 2011

Даже если вы считаете, что ваша попытка изменить контекстный документ с помощью for-each select="$root" неприемлема, это правильный подход. Так что используйте это, другого пути нет.

2 голосов
/ 16 декабря 2011

Рассматривали ли вы все вычисления, которые создают $ someXPathString с использованием ряда глобальных переменных?

<xsl:variable name="fooDocument" select="document('fooDocument.xml')"/>

<xsl:variable name="temp1"
  .. some computation using fooDocument ..
</xsl:variable>

<xsl:variable name="temp2"
  .. some computation using temp1 ..
</xsl:variable>

<xsl:variable name="someXPathString"
  .. some computation using temp2 ..
</xsl:variable>

<xsl:variable name="root" select="xalan:evaluate($someXPathString)"/>
...