2

有没有一种简单的组合 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>

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

4

3 回答 3

2

答案是:这取决于

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

这被称为管道方法- XML 沿着 XSLT 管道流动,被反复转换,直到结果从另一端出来,这是一种完全有效的方法。

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

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

于 2012-09-09T13:43:22.550 回答
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 点的可见性进行细粒度控制。

于 2012-09-09T14:35:05.840 回答
0

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

一旦 OP 编辑​​问题并提供源 XML 文档,我将很高兴更新此答案。

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

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

看看FXSL库,它包含 150 多个样式表模块,其中许多都导入了其他模块。

经验法则

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

于 2012-09-09T14:56:18.920 回答