假设 Saxon 9 PE 或 EE,也应该可以使用 XSLT 3.0 和xsl:evaluate
如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs math map mf"
version="3.0">
<xsl:output indent="yes"/>
<xsl:param name="paths-url" as="xs:string" select="'paths1.xml'"/>
<xsl:param name="paths-doc" as="document-node()" select="doc($paths-url)"/>
<xsl:variable name="main-root" select="/"/>
<xsl:variable
name="mapped-nodes">
<map>
<xsl:for-each select="$paths-doc/paths/xpath">
<xsl:variable name="node" as="node()?" select="mf:evaluate(@location, $main-root)"/>
<xsl:if test="$node">
<entry key="{generate-id($node)}">
<xsl:value-of select="@annotate"/>
</entry>
</xsl:if>
</xsl:for-each>
</map>
</xsl:variable>
<xsl:key name="node-by-id" match="map/entry" use="@key"/>
<xsl:function name="mf:evaluate" as="node()?">
<xsl:param name="path" as="xs:string"/>
<xsl:param name="context" as="node()"/>
<xsl:evaluate xpath="$path" context-item="$context"></xsl:evaluate>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()[key('node-by-id', generate-id(), $mapped-nodes)]">
<xsl:comment select="key('node-by-id', generate-id(), $mapped-nodes)"/>
<xsl:text> </xsl:text>
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是最初发布的代码的编辑版本,它使用 XSLT 3.0 映射功能而不是临时文档来存储通过动态 XPath 评估找到的节点的生成 id 与注释之间的关联:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs math map mf"
version="3.0">
<xsl:param name="paths-url" as="xs:string" select="'paths1.xml'"/>
<xsl:param name="paths-doc" as="document-node()" select="doc($paths-url)"/>
<xsl:output indent="yes"/>
<xsl:variable
name="mapped-nodes"
as="map(xs:string, xs:string)"
select="map:new(for $path in $paths-doc/paths/xpath, $node in mf:evaluate($path/@location, /) return map:entry(generate-id($node), string($path/@annotate)))"/>
<xsl:function name="mf:evaluate" as="node()?">
<xsl:param name="path" as="xs:string"/>
<xsl:param name="context" as="node()"/>
<xsl:evaluate xpath="$path" context-item="$context"></xsl:evaluate>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()[map:contains($mapped-nodes, generate-id())]">
<xsl:comment select="$mapped-nodes(generate-id())"/>
<xsl:text> </xsl:text>
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
作为第一个样式表,它需要 Saxon 9.5 PE 或 EE 才能运行。