XSLT - 如何组合XSLT文件

时间:2012-09-09 13:38:55

标签: xml xslt

是否有一种结合XSLT的简单方法。我是XSLT的新手,我开始了解如何创建它们以及使用它们来获得理想结果的有趣方法。但是目前我可以使用一个XSLT将输出转换为所需的输出; 然后直接我有另一个,另一个。每个XSLT都会将输出从一件事变为另一件事。

例如,这些是简单的XSLT来说明问题:

XSLT 1:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:r="http://www.castiron.com/response" exclude-result-prefixes="r">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/root">
        <xsl:element name="imageScene7Response"  xmlns="http://www.castiron.com/burberry/digitalcatalogue/response">
            <xsl:element name="rcode">0</xsl:element>
            <xsl:element name="rmessage">success</xsl:element>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="payload"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/root/payload">
        <xsl:if test="not(productId = preceding-sibling::payload/productId)">

            <xsl:element name="payload" xmlns="http://www.castiron.com/burberry/digitalcatalogue/response">
                <xsl:element name="productId">
                    <xsl:value-of select="productId"/>
                </xsl:element>
                <xsl:for-each select="../payload[productId = current()/productId]">
                    <xsl:choose>
                        <xsl:when test="type = '0' and preceding-sibling::payload/type = type and productId = preceding-sibling::payload/productId">
                            <xsl:element name="alternativeImages">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                        <xsl:when test="type = '0'">
                            <xsl:element name="mainImage">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                        <xsl:when test="type &gt; '0' and type &lt; '70'">
                            <xsl:element name="alternativeImages">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                        <xsl:when test="type = '70'">
                            <xsl:element name="video">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                        <xsl:when test="type = '80'">
                            <xsl:element name="lookbookImages">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                        <xsl:when test="type = 'sw'">
                            <xsl:element name="swatchImages">
                                <xsl:value-of select="url"/>
                            </xsl:element>
                        </xsl:when>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:element>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

然后:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match=
        "*[not(@*|*|comment()|processing-instruction()) 
        and normalize-space()=''
        ]"/>
</xsl:stylesheet>

然后是其他XSLT中的其他逻辑。

在单个组合XSLT中将模板放在另一个下面是否容易?

XML SNIPT

<?xml version="1.0"?>
<root>
    <payload>
        <productId>11111</productId>
        <type>0</type>
        <url>https://11111</url>
    </payload>
    <payload>
        <productId>11111</productId>
        <type>1</type>
        <url>https://11111</url>
    </payload>
    <payload>
        <productId>11111</productId>
        <type>1</type>
        <url></url>
    </payload>
    <payload>
        <productId>22222</productId>
        <type>0</type>
        <url>https://22222</url>
    </payload>
    <payload>
        <productId>22222</productId>
        <type>1</type>
        <url>https://22222</url>
    </payload>
    <payload>
        <productId>22222</productId>
        <type>sw</type>
        <url>https://22222</url>
    </payload>
    <payload>
        <productId>22222</productId>
        <type>sw</type>
        <url></url>
    </payload>
</root>

这不是最好的例子,但它会起作用!

3 个答案:

答案 0 :(得分:2)

答案是:取决于

如果您有多个XSL模板,那么它们可能会按顺序应用于XML - 例如,如果您有3个XSLT,则可能是第一个应用于原始文档,第二次转换到第一次转换的结果,第三次转换为第二次转换的结果。

这被称为the pipeline approach - XML沿着XSLT管道流动,被重复转换,直到结果从另一端流出,并且是一种非常有效的方法。

如果XSLT的设计是按顺序应用的,那么最好将它们保持原样 - 将它们组合成一个巨大的XSLT是可能的,但是操作和维护非常棘手,因为你必须传递XML节点集从模板到模板。讨论了这种方法here,尽管我不同意作者的结论,即这是一种更纯粹的方法。

在上面的示例中,您有2个清晰的XSLT。第一个显然是结构化的 - 它旨在将XML响应的结构转换为另一个XML文档。您拥有的第二个XSLT几乎是一个实用程序XSLT - 它似乎旨在去除任何不属于属性或属性的东西。在这种情况下,最好将它们应用于XML响应消息。

答案 1 :(得分:1)

在XSLT 1.0和2.0中,有两个用于组合样式表的本机指令:xsl:import和xsl:include。在XSLT 3.0中,有第三种机制,我将在稍后介绍。

导入说明看起来像这样......

<xsl:import href="my-other-transform.xsl" />

包含说明类似

<xsl:include href="my-other-transform.xsl" />

xsl:import引用另一个样式表并使其模板可用,但优先级低于主样式表的模板。 xsl:include表示好像指令被包含的样式表的逐字副本替换。

一般来说,制作顶级样式表的首选技术是非常特定于您要解决的问题,并导入样式表,其中导入的样式表更通用和通用

如果您在客户端使用XSLT 1.0,我不知道,但我怀疑浏览器对xsl:import和xsl:include的支持将受到限制。如果您正在使用XSLT 1.0服务器端,那么你会感到羞耻!您没有理由不升级到XSLT 2.0。

在XSLT 3.0中,您可以使用xsl:package指令声明一个独立的模块集合,其中包含对API点的可见性的细粒度控制。

答案 2 :(得分:0)

可以改进第一次转换,以便第二次转换甚至可以消除

我很乐意在OP编辑问题并提供源XML文档后更新此答案。

至于组合不同转换的一般方法

使用<xsl:import>是您的朋友。

请查看 FXSL 库,其中包含超过150个样式表模块,其中许多模式导入其他模块。

经验法则

每当同一样式表模块中包含的模板或模板组包含可能在多个案例中使用的有用功能时,最好以这样的方式编写这些模板或模板,以便可以方便地导入它们由需要此功能的其他更具体的样式表模块,因此避免在每个特定情况下重新实现此功能。