昨天我问a question有关从XSLT动态加载外部XML的问题。它得到了答复,但现在我有另一个问题。如果您阅读该问题,您会在第三级看到<include ref="/path/to/some.xml" />
。如果<include>
发生的级别变化怎么办?
有没有办法动态选择从原始文件中出现的相同级别的XML中提取节点?
修改 要明确:我在谈论XML中的“元素路径”(XML中include元素的位置),而不是文件路径。
merge.xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output indent="yes" method="xml" encoding="utf-8"
omit-xml-declaration="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="include">
<!-- the depth of the extraction path (fruit/*/*/*... etc) should
be based on the position of the matched <include> element -->
<xsl:apply-templates select="document(@ref)/fruit/*/*/*"/>
</xsl:template>
</xsl:stylesheet>
fruit.xml:
<fruit>
<local>
<apples>
<include ref="apples.xml" />
</apples>
</local>
<exotic>
<bananas>
<deeperlevel>
<include ref="bananas.xml" />
</deeperlevel>
</bananas>
<oranges>
<include ref="oranges.xml" />
</oranges>
</exotic>
</fruit>
bananans.xml:
<fruit>
<exotic>
<bananas>
<deeperlevel>
<banana type="chiquita" color="yellow" />
<banana type="generic" color="yellow" />
</deeperlevel>
</bananas>
</exotic>
</fruit>
结果:
<fruit>
<local>
<apples>
<apple type="jonagold" color="red"/><apple type="granny-smith" color="green"/>
</apples>
</local>
<exotic>
<bananas>
<deeperlevel>
<deeperlevel> <!-- I don't want the second <deeperlevel> here, instead
<bananas .../> should be extracted, right after the
first <deeperlevel> -->
<banana type="chiquita" color="yellow"/>
<banana type="generic" color="yellow"/>
</deeperlevel>
</deeperlevel>
</bananas>
<oranges>
<orange type="juice-orange" color="orange"/><orange type="red-orange" color="red"/>
</oranges>
</exotic>
</fruit>
答案 0 :(得分:0)
我找到了解决问题的方法。它不是非常好的恕我直言,因为它是一个“eval”型解决方案,但它的工作原理。我在this question的答案中对我的问题,动态XPath评估扩展(dyn:evaluate()
)应用了第3个建议。幸运的是xsltproc
库中的libxslt
工具(通过macports 1.1.27安装)支持它。
我会暂时搁置这个问题,也许某人有更好的解决方案。
XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dyn="http://exslt.org/dynamic"
extension-element-prefixes="dyn">
<xsl:output indent="yes" method="xml" encoding="utf-8"
omit-xml-declaration="yes" />
<xsl:template match="@*|node()">
<xsl:param name="depth" select="'/*'" />
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:with-param name="depth" select="concat($depth, '/*')" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="include">
<xsl:param name="depth" />
<xsl:apply-templates select="dyn:evaluate(concat('document(@ref)', $depth))">
<xsl:with-param name="depth" select="$depth" />
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>