假設撒克遜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。
您的示例在「povided this input XML file」標題下提供,沒有帶'x'屬性的'c'元素,爲什麼輸出突然有一個?我想你發佈了錯誤的輸入樣本。 –
很好,@MartinHonnen。當我編輯我的答案以顯示更強大的匹配示例時,我忽略了更新該輸入XML。現在修復。謝謝。 – kjhughes
我認爲這可能是我會採取的方法,因爲在這一點上我完全不熟悉3.0。我已經嘗試過使用'saxon:evaluate'函數,我懷疑它與Martin的解決方案大致相同。關於這個解決方案,我還沒有找到一種方法來註釋屬性節點的xpath。例如' 「/根/ C/@ X」'。 – stand