簡體   English   中英

XSLT 1.0-在另一個模板的結果上運行一個模板

[英]XSLT 1.0 - Running a template on the result of another template

我想知道XSLT 1.0如何完成這種轉換,該轉換將一個模板的結果作為單個.xslt文件中另一個模板的輸入傳遞:

原始XML輸入>調用模板(1)>重新格式化的XML>重新格式化的XML上的調用模板(2)

案件:

我想編寫一個模板來重新排列xml,以使屬性成為元素。 然后在第一個生成的xml上運行另一個模板,以刪除重復項。 我可以有兩個xsl文件,並將第一個轉換的結果傳遞給第二個。 但是,我想在一個xslt中做到這一點。

原始輸入xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <resource>
        <properties>
            <property name="name" value="Foo"/>
            <property name="service" value="Bar"/>
            <property name="version" value="1"/>
        </properties>
    </resource>
    <resource>
        <properties>
            <property name="name" value="Foo"/>
            <property name="service" value="Bar"/>
            <property name="version" value="2"/>
        </properties>
    </resource>
    <resource>
        <properties>
            <property name="name" value="AnotherFoo"/>
            <property name="service" value="AnotherBar"/>
            <property name="version" value="1"/>
        </properties>a
    </resource>
</resources>

當我應用以下xslt時:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="msxsl">

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

    <xsl:template name="attributes-to-elements" match="/resources">
        <xsl:call-template name="get-resources" />
    </xsl:template>

    <xsl:template name="get-resources">
        <xsl:text>&#xa;</xsl:text>
        <products>
            <xsl:for-each select="resource">
                <xsl:call-template name="convert-attributes-to-elements" />
            </xsl:for-each>
        </products>
    </xsl:template>

    <xsl:template name="convert-attributes-to-elements">
        <product>
            <name>
                <xsl:value-of select="properties/property[@name='name']/@value" />
            </name>
            <service>
                <xsl:value-of select="properties/property[@name='service']/@value" />
            </service>
        </product>
    </xsl:template>
</xsl:stylesheet>

我能夠不使用版本重新格式化xml,並獲得不包含版本且屬性已成為元素​​的輸出:

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product>
        <name>Foo</name>
        <service>Bar</service>
    </product>
    <product>
        <name>Foo</name>
        <service>Bar</service>
    </product>
    <product>
        <name>AnotherFoo</name>
        <service>AnotherBar</service>
    </product>
</products>

現在,我想要的是將經過修改的xml作為輸入xml傳遞給某個模板,並刪除重復項。 最后,我想獲得一個像這樣的xml:

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product>
        <name>Foo</name>
        <service>Bar</service>
    </product>
    <product>
        <name>AnotherFoo</name>
        <service>AnotherBar</service>
    </product>
</products>

如果需要,所有這些都可以通過一次操作完成:

XSLT 1.0

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

<xsl:key name="k" 
         match="resource" 
         use="concat(properties/property[@name='name']/@value, '|', properties/property[@name='service']/@value)"
/>

<xsl:template match="/resources">
    <products>
        <xsl:apply-templates select="resource[count(. | key('k', concat(properties/property[@name='name']/@value, '|',      properties/property[@name='service']/@value))[1]) = 1]"/>
    </products>
</xsl:template>

<xsl:template match="resource">
    <product>
        <xsl:copy-of select="@id"/>
        <name>
            <xsl:value-of select="properties/property[@name='name']/@value" />
        </name>
        <service>
            <xsl:value-of select="properties/property[@name='service']/@value" />
        </service>
    </product>
</xsl:template>

</xsl:stylesheet>

我將使用一種模式來分離處理步驟,當然,在XSLT 1.0中,您還需要一個擴展功能,例如exsl:node-setmsxsl:node-set ,以便能夠進一步處理在另一個模板中創建的結果樹片段:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="msxsl exsl">

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

    <xsl:key name="group" match="product" use="concat(name, '|', service)"/>

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

    <xsl:template match="product[not(generate-id() = generate-id(key('group', concat(name, '|', service))[1]))]" mode="step2"/>

    <xsl:template name="attributes-to-elements" match="/resources">
        <xsl:variable name="step1-rtf">
          <xsl:call-template name="get-resources" />
        </xsl:variable>
        <xsl:apply-templates select="exsl:node-set($step1-rtf)/*" mode="step2"/>
    </xsl:template>

    <xsl:template name="get-resources">
        <xsl:text>&#xa;</xsl:text>
        <products>
            <xsl:for-each select="resource">
                <xsl:call-template name="convert-attributes-to-elements" />
            </xsl:for-each>
        </products>
    </xsl:template>

    <xsl:template name="convert-attributes-to-elements">
        <product>
            <name>
                <xsl:value-of select="properties/property[@name='name']/@value" />
            </name>
            <service>
                <xsl:value-of select="properties/property[@name='service']/@value" />
            </service>
        </product>
    </xsl:template>
</xsl:stylesheet>

您將需要檢查XSLT處理器是否支持exsl:node-set ,而MSXML需要使用msxsl:node-set

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM