使用XSL转换转换后的XML?

时间:2012-01-11 16:33:45

标签: xml xslt

假设我有一些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忍者......

提前致谢

2 个答案:

答案 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 -->