XSL 1.0通过Munchian和多种匹配模式区分

时间:2010-08-06 03:56:35

标签: xslt

学习XSL,此时降级为XSL 1.0,尝试生成一个不同的集合,并使用匹配模式构造执行后续传递。

如果没有引入模式,一切都很顺利。

一旦引入模式,翻译就会失败。

任何帮助都将不胜感激。

Exempliary xml:

    <?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC2" catatt="AD2">C2</category>
        <desc>D2</desc>
    </node>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC3" catatt="AD3">C3</category>
        <desc>D3</desc>
    </node>
</dataset>

样品Munchian产生不同的记录。

    <?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/><!-- New document created with EditiX at Thu Aug 05 16:51:01 PDT 2010 -->
    <xsl:key name="nodekey" match="node/category" use="concat(@catat,'_',@catatt)"/>
    <xsl:template match="dataset">
        <CAT>
            <xsl:apply-templates />
        </CAT>
    </xsl:template>
    <xsl:template match="dataset" >
        <CATD>
            <xsl:for-each select="node/category[generate-id()= generate-id(key('nodekey',concat(@catat,'_',@catatt))[1])]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </CATD>
    </xsl:template>
</xsl:stylesheet>

示例输出:

<?xml version="1.0" encoding="UTF-8"?>
<CATD xmlns:exslt="http://exslt.org/common">
   <CAT_D>AC1_AD1_C1</CAT_D>
   <CAT_D>AC2_AD2_C2</CAT_D>
   <CAT_D>AC3_AD3_C3</CAT_D>
</CATD>

但是,添加模式时,相同的翻译会失败吗?

    <?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/><!-- New document created with EditiX at Thu Aug 05 16:51:01 PDT 2010 -->
    <xsl:key name="nodekey" match="node/category" use="concat(@catat,'_',@catatt)"/>
    <xsl:template match="dataset">
        <UCAT>
            <xsl:apply-templates mode="ucatmode"/>
        </UCAT>
        <DCAT>
            <xsl:apply-templates mode="catmode"/>
        </DCAT>
    </xsl:template>
    <xsl:template match="dataset" mode="ucatmode">
        <DESC>
            <xsl:for-each select="node/category[generate-id()= generate-id(key('nodekey',concat(@catat,'_',@catatt))[1])]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </DESC>
    </xsl:template>
    <xsl:template match="dataset/node/desc" mode="catmode">
        <CATQ>
            <xsl:value-of select="."/>
        </CATQ>
    </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:2)

  

但是,当添加相同的模式时   翻译失败?

您的问题在于此代码

<xsl:template match="dataset">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

<xsl:template match="dataset" mode="ucatmode">

上述说明:

<xsl:apply-templates mode="ucatmode"/>

是;

的缩写
<xsl:apply-templates select="child::node()"
     mode="ucatmode"/>

dataset元素的子元素只是名为node的元素和仅限空格的文本节点。您的代码中没有任何模板位于名为ucatmode的模式中且与node元素匹配。

因此,没有选择模板进行处理,XSLT处理器使用内置模板(它们可用于任何模式)。 XSLT内置模板会导致所有文本节点被复制 - 这就是你得到的。

指令存在完全相同的问题

<xsl:apply-templates mode="catmode"/>

解决方案:替换:

<xsl:template match="dataset">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

<强>与

<xsl:template match="/">
    <UCAT>
        <xsl:apply-templates mode="ucatmode"/>
    </UCAT>
    <DCAT>
        <xsl:apply-templates mode="catmode"/>
    </DCAT>
</xsl:template>

此模板现在与文档节点匹配,其唯一(顶部)子项是dataset元素,现在将选择与dataset匹配的两个模式模板进行处理。

您仍然需要替换:

<xsl:apply-templates mode="catmode"/>

使用:

    <xsl:apply-templates mode="catmode"
         select="dataset/node/desc"/>

因为desc不是dataset的孩子,并且dataset的所有后代都会再次涉及内置模板处理,但desc除外。< / p>

一个小的额外修正是消除所有仅限空格的文本节点 - 这可以通过以下XSLT指令方便地实现:

<xsl:strip-space elements="*"/>

另一个小改进是防止exslt:前缀出现在每个文字结果元素中。这是通过添加属性:

来实现的
exclude-result-prefixes="exslt"

<xsl:stylesheet>指令。

完整的更正转换(正确缩进以提高可读性)因此

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

    <xsl:key name="nodekey" match="node/category"
    use="concat(@catat,'_',@catatt)"/>

    <xsl:template match="/">
        <UCAT>
            <xsl:apply-templates mode="ucatmode"/>
        </UCAT>
        <DCAT>
            <xsl:apply-templates mode="catmode"
                 select="dataset/node/desc"/>
        </DCAT>
    </xsl:template>

    <xsl:template match="dataset" mode="ucatmode">
        <DESC>
            <xsl:for-each select=
             "node/category
                   [generate-id()
                   =
                    generate-id(key('nodekey',
                                     concat(@catat,'_',@catatt)
                                     )[1]
                                )
                    ]">
                <CAT_D>
                    <xsl:value-of select="concat(@catat,'_',@catatt)"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="."/>
                </CAT_D>
            </xsl:for-each>
        </DESC>
    </xsl:template>

    <xsl:template match="dataset/node/desc" mode="catmode">
        <CATQ>
            <xsl:value-of select="."/>
        </CATQ>
    </xsl:template>
</xsl:stylesheet>

将其应用于提供的XML文档

<dataset>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC2" catatt="AD2">C2</category>
        <desc>D2</desc>
    </node>
    <node>
        <category comat="0" catat="AC1" catatt="AD1">C1</category>
        <desc>D1</desc>
    </node>
    <node>
        <category comat="0" catat="AC3" catatt="AD3">C3</category>
        <desc>D3</desc>
    </node>
</dataset>

产生了想要的正确结果

<UCAT>
   <DESC>
      <CAT_D>AC1_AD1_C1</CAT_D>
      <CAT_D>AC2_AD2_C2</CAT_D>
      <CAT_D>AC3_AD3_C3</CAT_D>
   </DESC>
</UCAT>
<DCAT>
   <CATQ>D1</CATQ>
   <CATQ>D2</CATQ>
   <CATQ>D1</CATQ>
   <CATQ>D3</CATQ>
</DCAT>

答案 1 :(得分:0)

感谢Dimitre,您的建议符合标准。

添加正式解决方案以供参考。

<?xml version="1.0" encoding="ISO-8859-1"?>
  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt" >
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="distinct-CompositeKeyNOS" match="Downloads/Download[@ParentDownloadID='0']" use="concat(@Version,'_',@DownloadType,'_',@Name,'_',@IsBeta)"/>
<xsl:template match="/">
<NotifiusExportData>

            <xsl:apply-templates mode="OSAgnostic">
    </xsl:apply-templates> 

            <xsl:apply-templates mode="english">
    </xsl:apply-templates> 

            <xsl:apply-templates mode="DevicesLangCodes">
    </xsl:apply-templates> 
</NotifiusExportData>
</xsl:template>



    <xsl:template match="NotifiusExportData" mode="OSAgnostic">

        <xsl:for-each select="Downloads/Download[generate-id()= generate-id(key('distinct-CompositeKeyNOS',concat(@Version,'_',@DownloadType,'_',@Name,'_',@IsBeta))[1])]">
                <xsl:sort select="@Version" order="descending" data-type="number"/>
                <xsl:sort select="@DownloadType" order="ascending"/>
                <xsl:sort select="@Name" order="ascending"/>
                <xsl:sort select="@OS" order="descending" data-type="number"/>
                <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
                <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <Downloads>
                <CompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </CompositeKeyNOS>
                <CompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </CompositeKey>
                <ParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </ParentDownloadID>
                <DownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </DownloadId>
                <Release>
                    <xsl:value-of select="@Release"/>
                </Release>
                <Version>
                    <xsl:value-of select="@Version"/>
                </Version>
                <DetailsURL>
                    <xsl:value-of select="@DetailsURL"/>
                </DetailsURL>
                <IsBeta>
                    <xsl:value-of select="@IsBeta"/>
                </IsBeta>
                <ReleaseDate>
                    <xsl:value-of select="@ReleaseDate"/>
                </ReleaseDate>
                <DownloadType>
                    <xsl:value-of select="@DownloadType"/>
                </DownloadType>
                <OS>
                    <xsl:value-of select="@OS"/>
                </OS>
                <Is64Bit>
                    <xsl:value-of select="@Is64Bit"/>
                </Is64Bit>
                <LangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </LangCode5>
                <Name>
                    <xsl:value-of select="@Name"/>
                </Name>
                <GraphicsVersion>
                    <xsl:value-of select="@GraphicsVersion"/>
                </GraphicsVersion>
                <USBEmitterVersion>
                    <xsl:value-of select="@USBEmitterVersion"/>
                </USBEmitterVersion>
            </Downloads>

        </xsl:for-each>

    </xsl:template>


    <xsl:template match="NotifiusExportData/Downloads" mode="english"><!-- xsl:for-each select="." --><!--xsl:if test="@ParentDownloadID=0"-->
        <xsl:for-each select="Download[@ParentDownloadID='0']">
            <xsl:sort select="@Version" order="descending" data-type="number"/>
            <xsl:sort select="@DownloadType" order="ascending"/>
            <xsl:sort select="@Name" order="ascending"/>
            <xsl:sort select="@OS" order="descending" data-type="number"/>
            <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
            <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <NDownloads>
                <NCompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NCompositeKeyNOS>
                <NCompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NCompositeKey>
                <ParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </ParentDownloadID>
                <DownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </DownloadId>
                <Release>
                    <xsl:value-of select="@Release"/>
                </Release>
                <Version>
                    <xsl:value-of select="@Version"/>
                </Version>
                <DetailsURL>
                    <xsl:value-of select="@DetailsURL"/>
                </DetailsURL>
                <IsBeta>
                    <xsl:value-of select="@IsBeta"/>
                </IsBeta>
                <ReleaseDate>
                    <xsl:value-of select="@ReleaseDate"/>
                </ReleaseDate>
                <DownloadType>
                    <xsl:value-of select="@DownloadType"/>
                </DownloadType>
                <OS>
                    <xsl:value-of select="@OS"/>
                </OS>
                <Is64Bit>
                    <xsl:value-of select="@Is64Bit"/>
                </Is64Bit>
                <LangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </LangCode5>
                <Name>
                    <xsl:value-of select="@Name"/>
                </Name>
                <GraphicsVersion>
                    <xsl:value-of select="@GraphicsVersion"/>
                </GraphicsVersion>
                <USBEmitterVersion>
                    <xsl:value-of select="@USBEmitterVersion"/>
                </USBEmitterVersion>
            </NDownloads><!--/xsl:if --><!-- /xsl:for-each -->
        </xsl:for-each>
    </xsl:template><!-- xsl:template match="Download" mode="DevicesLangCodes" -->



<!-- xsl:template match="Download" mode="DevicesLangCodes" -->

    <xsl:template match="NotifiusExportData/Downloads" mode="DevicesLangCodes"><!-- xsl:for-each select="." --><!-- xsl:if test="@ParentDownloadID!=0" -->
        <xsl:for-each select="Download">
            <xsl:sort select="@Version" order="descending" data-type="number"/>
            <xsl:sort select="@DownloadType" order="ascending"/>
            <xsl:sort select="@Name" order="ascending"/>
            <xsl:sort select="@LangCode5" order="ascending"/>
            <xsl:sort select="@OS" order="descending" data-type="number"/>
            <xsl:sort select="@Is64Bit" order="descending" data-type="number"/>
            <xsl:sort select="@IsBeta" order="ascending" data-type="number"/>
            <NNDownloads>
                <NNCompositeKeyNOS>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NNCompositeKeyNOS>
                <NNCompositeKey>
                    <xsl:value-of select="@Version"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@DownloadType"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Name"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@Is64Bit"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@IsBeta"/>
                </NNCompositeKey>
                <NParentDownloadID>
                    <xsl:value-of select="@ParentDownloadID"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </NParentDownloadID>
                <NDownloadId>
                    <xsl:value-of select="@DownloadId"/>
                    <xsl:text>_</xsl:text>
                    <xsl:value-of select="@OS"/>
                </NDownloadId>
                <NLangCode5>
                    <xsl:value-of select="@LangCode5"/>
                </NLangCode5>
                <xsl:call-template name="groupLangCodes"/>
                <xsl:call-template name="groupDeviceIds"/>
            </NNDownloads>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="groupLangCodes" match="LangCodes">
        <LangCodes>
            <xsl:call-template name="getLangCodeIds"/>
        </LangCodes>
    </xsl:template>
    <xsl:template name="groupDeviceIds" match="DeviceIds">
        <DeviceIds>
            <xsl:call-template name="getDeviceIds"/>
        </DeviceIds>
    </xsl:template>
    <xsl:template name="getLangCodeIds">
        <xsl:for-each select="LangCodes/LangCode">
            <xsl:value-of select="@Id"/>
            <xsl:text> </xsl:text>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="getDeviceIds">
        <xsl:for-each select="DeviceIds/DeviceId">
            <xsl:value-of select="@Id"/>
            <xsl:text> </xsl:text>
        </xsl:for-each>
    </xsl:template>

  </xsl:stylesheet>