学习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>
答案 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>