【问题标题】:Transforming transformed XML with XSL?用 XSL 转换转换后的 XML?
【发布时间】:2012-01-11 16:33:44
【问题描述】:

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

提前致谢

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    是的,将复杂转换分解为一系列简单转换是 XSLT 的标准设计模式,强烈推荐。

    有两种方法:单样式表和多样式表。在单样式表管道中,您通常使用模式,转换的每个阶段使用一种模式。中间结果保存在变量中(这意味着在 XSLT 1.0 中,您需要使用 xx:node-set() 使一个阶段的结果可用于下一阶段的处理)。

    使用多个样式表 - 一系列转换,每个都有自己的 XSLT 样式表 - 需要更多的工作来设置,因为它需要一些控制机制来运行管道。但最终它通常会更好,因为代码不那么复杂并且更可重用。您可以使用多种技术来控制管道 - Ant、XProc、shell 脚本、xmlsh、Orbeon、Cocoon 或普通的 Java。

    【讨论】:

    • 谢谢,迈克尔。是的,我想到了多个样式表,这是一种选择,但在一张表中实现它会很好。有时像这样的 XSL 作为 API 感觉非常有限(我知道,它大约有一千年的历史了)。再次感谢。
    【解决方案2】:

    您可以在模板上使用模式多次处理节点,但具有不同的转换。所以你可以做例如

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

    【讨论】:

    • 谢谢,马丁。实际上,我确实有将第一个生成的 XML 放入节点集然后尝试对其进行转换的想法;但我以某种方式遇到了应用程序错误(无限循环)。我会更多地研究你的答案,看看我的进展如何。
    猜你喜欢
    • 2016-02-12
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多