XSLT:XPath上下文和文档()

时间:2011-12-16 11:07:53

标签: xslt xpath xslt-1.0 xalan

我有一个像这样的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源。我找到的非常 hacky解决方法就是:

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

(无用的)for-each循环将上下文更改回主XML源,因此XPath正确评估。但显然,这不是一个可以接受的解决方案。

有没有办法正确,或者有人可以提出更好的解决方法吗?

2 个答案:

答案 0 :(得分:3)

即使您认为使用for-each select="$root"尝试更改上下文文档也是不可接受的,这是正确的方法。所以使用它,没有别的办法。

答案 1 :(得分:2)

您是否考虑过使用一系列全局变量进行构造$ 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)"/>