XSLT - 如何合并XSLT文件

3
有没有一种简单的方法来合并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片段

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

这并不是最好的例子,但它能够运作!


请编辑问题并提供源XML文档。第一个转换可以改进。而且似乎可以消除第二个转换的需要。至于不同转换组合的一般方法,使用<xsl:import>是您的好朋友。请查看FXSL库,其中包含150多个样式表模块,其中许多导入其他模块。 - Dimitre Novatchev
3个回答

2
答案是:这取决于具体情况 如果您有多个XSL模板,则可能打算将它们按顺序应用于XML,例如,如果您有3个XSLT,则第一个可能应用于原始文档,第二个应用于第一次转换的结果,第三个应用于第二次转换的结果。
这被称为管道方法 - XML沿着XSLT管道流动,不断进行转换,直到结果从另一端出来并且这是完全有效的方法。
如果XSLT旨在按顺序应用,则最好保持它们的方式 - 将它们混合到一个巨大的XSLT中是可能的,但是很难操作和维护,因为您必须从模板传递XML节点集。该方法在此处进行了讨论,尽管我不同意作者的结论认为这是更纯粹的方法。
在上面的示例中,您有2个明确的XSLT。第一个显然是结构性的 - 它旨在将XML响应的结构转换为另一个XML文档。第二个XSLT几乎是实用程序XSLT - 它似乎旨在剥离除属性或属性之外的任何内容。在这种情况下,最好按顺序将它们应用于XML响应消息。

完美,谢谢。我正在寻找的是这一部分:“如果您有多个XSL模板,则可能打算按顺序将它们应用于XML - 因此,例如,如果您有3个XSLT,则第一个可能适用于原始文档,第二个适用于第一个转换的结果,第三个适用于第二个转换的结果。这被称为管道方法 - XML沿着XSLT管道流动,不断转换,直到结果从另一端出来,并且是一种完全有效的方法。” - mmkd
如果您想要多次操作XML,最好使用多个不同的XSLT。谢谢! - mmkd
这就是有趣的地方...我使用IBM的ETL工具Cast Iron。但是我的操作非常受限,我只能应用XSLT,因此我只需复制样式表并将XML指向它进行转换。 - mmkd
好的,另外一个快速问题...我怎样可以合并上述两个样式表?我想要移除所有空标签。 - mmkd
@MMKD 如果你有一个XML文档的例子,我可以尝试向你展示如何完成这个操作 - 最终,你可能能够限制第一个转换中的copy-of语句,使其仅复制节点和属性,从而消除第二个转换的需要。 - dash
显示剩余2条评论

2
在XSLT 1.0和2.0中,有两个原生指令用于组合样式表:xsl:import和xsl:include。在XSLT 3.0中,有第三种机制,稍后我会讲到。
导入指令的格式如下...
<xsl:import href="my-other-transform.xsl" />

而且include指令也很相似

<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 点的可见性进行细粒度控制。


Sean,请在推荐XSLT 3.0功能时要谨慎。XSLT 3.0仍然是一个工作草案(WD),许多功能可能会从它们当前的定义中改变(甚至完全消失)。据我所知,目前没有任何现有的XSLT 3.0实现支持包。 - Dimitre Novatchev

0

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

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

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

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

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

经验法则:

每当同一样式表模块中包含有用功能的模板或一组模板可能在多种情况下使用时,编写这些模板的方式应该是可以方便地通过其他更具体的样式表模块导入它们,这些模块需要此功能,从而避免在每种不同的特定情况下重新实现此功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接