【问题标题】:XSLT: XPath context and document()XSLT:XPath 上下文和文档()
【发布时间】:2011-12-16 11:07:53
【问题描述】:

我有一个这样的 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 源。我发现的 very hacky 解决方法是这样的:

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

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

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

【问题讨论】:

    标签: xslt xpath xslt-1.0 xalan


    【解决方案1】:

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

    【讨论】:

    • 我同意 for-each 是更改上下文文档的好方法(如果有点不直观),但马丁你肯定不是说没有其他方法。例如。 apply-templates select="$root"(有无模式)也会设置上下文文档,对吧?
    • 我没有找到任何其他可行的方法来更改上下文文档。
    【解决方案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)"/>
    

    【讨论】:

    • 如果我选择将 fooDocument 的所有内容复制到一个全局变量中并在其上使用 xalan:nodeset() ,这将起作用。由于 fooDocument 包含任意长度的序列,我无法将其拆分为固定数量的包含原始值的全局变量。为了可读性,这绝对是一种选择。编辑:再想一想,当我在这个全局变量上使用 apply-templates 时,我的上下文仍然不在 XML 源上,而是在包含 xalan:nodeset() 调用结果的变量上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2019-03-10
    • 2011-11-16
    • 2011-12-19
    • 1970-01-01
    相关资源
    最近更新 更多