如何调用xsl:evaluate并保留结果的上下文信息?
问题:使用
<xsl:evaluate>无法访问结果的祖先节点,如何保留上下文信息? 我在使用<xsl:evaluate>计算XPath表达式时,发现结果和直接计算XPath的情况有差异——直接计算时能访问结果的祖先节点,但用<xsl:evaluate>就不行。有没有办法保留<xsl:evaluate>结果的上下文信息?
我的XSLT代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"> <xsl:output method="text" encoding="UTF-8" /> <xsl:template match="/one"> <xsl:value-of select="name()" /> <xsl:text>
</xsl:text> <xsl:variable name="xpath"> <xsl:text>//three</xsl:text> </xsl:variable> <xsl:variable name="matches1"> <xsl:evaluate xpath="$xpath" context-item="." /> </xsl:variable> <xsl:for-each select="$matches1/*"> <xsl:value-of select="name()" /> <xsl:text>,</xsl:text> <xsl:value-of select="name(parent::*)" /> <xsl:text>
</xsl:text> </xsl:for-each> <xsl:variable name="matches2" select="//three" /> <xsl:for-each select="$matches2"> <xsl:value-of select="name()" /> <xsl:text>,</xsl:text> <xsl:value-of select="name(parent::*)" /> <xsl:text>
</xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
输入文件内容
<one> <two> <three /> <three /> </two> <two /> </one>
当前输出结果
one three, three, three,two three,two
解决方案
问题出在$matches1的定义方式上:你用内容模板(未指定select属性)包裹<xsl:evaluate>,这会把<xsl:evaluate>返回的节点序列复制到一个临时树片段中,复制后的节点与原文档的上下文完全断开,因此无法访问祖先节点。
只需修改$matches1的定义,给变量添加select属性直接引用<xsl:evaluate>的结果,就能保留原节点的上下文关联:
<xsl:variable name="matches1" select="xsl:evaluate(xpath := $xpath, context-item := .)" />
同时,后续遍历的select="$matches1/*"也需要改成select="$matches1"——因为现在$matches1直接持有节点序列,不需要再取子节点:
<xsl:for-each select="$matches1"> <xsl:value-of select="name()" /> <xsl:text>,</xsl:text> <xsl:value-of select="name(parent::*)" /> <xsl:text>
</xsl:text> </xsl:for-each>
修改后,$matches1会直接引用原文档中的<three>节点,遍历的时候就能正常访问父节点<two>,输出结果会和matches2的部分完全一致。
内容的提问来源于stack exchange,提问作者wrgrs
相关产品推荐
相关产品推荐

