假设我有一些XSL转换XML。是否有可能相同的XSL表格在生成的XML上运行第二次扫描?例如,假设我的XSL转为
<xml>
<animal><dog>Rex</dog></animal>
<animal><dog>Henry</dog></animal>
<animal><dog>Fido</dog></animal>
</xml>
到
<xml>
<dog>Rex</dog>
<dog>Henry</dog>
<dog>Fido</dog>
</xml>
我不想输出那个;相反,我想基于THAT执行更多的XSL,即结果,XML结构。
一个实际的例子?我想向每个狗节点追加它所拥有的犬兄弟姐妹的数量。所以它最终会像:
<xml>
<dog>Rex (2)</dog>
<dog>Henry (1)</dog>
<dog>Fido (0)</dog>
</xml>
这不能在第一次扫描时完成,因为在开头的XML中,狗节点不是兄弟姐妹 - 它们每个都生活在动物节点内。
[编辑:我知道可以通过查询父动物节点的索引来完成,但这仅适用于这个人为的例子;一般来说,我仍然需要知道如何对转换的XML采取行动 - 如果它甚至可能的话]
我希望这有点道理。如果有一个非常简单的方法可以做到这一点,那么请放轻松,因为我不是XSL忍者......
提前致谢
答案 0 :(得分:2)
是的,将复杂转换分解为一系列简单转换是XSLT的标准设计模式,强烈建议使用。
有两种方法:单样式表和多样式表。在单样式表管道中,您通常使用模式,每个阶段的转换都使用一种模式。中间结果保存在变量中(这意味着在XSLT 1.0中,您需要使用xx:node-set()使一个阶段的结果可用于下一阶段的处理。)
使用多个样式表 - 一系列转换,每个转换都有自己的XSLT样式表 - 设置起来需要更多工作,因为它需要一些控制机制来运行管道。但最终它通常更好,因为代码不那么复杂,而且更可重用。您可以使用许多技术来控制管道 - Ant,XProc,shell脚本,xmlsh,Orbeon,Coccoon或普通旧Java。
答案 1 :(得分:1)
您可以使用模板上的模式多次处理节点但具有不同的转换。所以你可以这样做。
<xsl:variable name="result1">
<xsl:apply-templates select="xml" mode="m1"/>
</xsl:variable>
<xsl:variable name="result2">
<xsl:apply-templates select="$result1/xml" mode="m2"/>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$result2"/>
</xsl:template>
<!-- now put templates for the modes here -->
上面的内容仅适用于XSLT 2.0,但是,使用XSLT 1.0,您的缺点是临时结果是结果树片段,您需要先将其转换为节点集,并使用exsl:node-set等扩展函数所以使用XSLT 1.0,你需要例如
<xsl:variable name="result1">
<xsl:apply-templates select="xml" mode="m1"/>
</xsl:variable>
<xsl:variable name="result2">
<xsl:apply-templates select="exsl:node-set($result1)/xml" mode="m2"/>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$result2"/>
</xsl:template>
<!-- now put templates for the modes here -->