我试图弄清楚如何避免结果集中的重复 在应用XSLT转换时(我正在使用XSLT 1.0)
这是XML源:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="1.xsl"?>
<root>
<item>
<code>AA</code>
<included-code>XX</included-code>
<included-code>YY</included-code>
<included-code>WW</included-code>
</item>
<item>
<code>BB</code>
<included-code>ZZ</included-code>
<included-code>XX</included-code>
<included-code>YY</included-code>
</item>
<item>
<code>CC</code>
<included-code>VV</included-code>
<included-code>XX</included-code>
<included-code>WW</included-code>
</item>
</root>
这是样式表:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<result>
<xsl:apply-templates/>
</result>
</xsl:template>
<xsl:template match="item">
<new-item>
<code><xsl:value-of select="code"/></code>
<xsl:variable name="main_code"><xsl:value-of select="code"/></xsl:variable>
<xsl:for-each select="included-code">
<xsl:variable name="current_code"><xsl:value-of select="text()"/></xsl:variable>
<included-code><xsl:value-of select="$current_code"/></included-code>
<xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]">
<included-code><xsl:value-of select="code"/></included-code>
</xsl:for-each>
</xsl:for-each>
</new-item>
</xsl:template>
</xsl:stylesheet>
结果如下:
<?xml version="1.0" encoding="UTF-8"?><result>
<new-item>
<code>AA</code>
<included-code>XX</included-code>
<included-code>BB</included-code>
<included-code>CC</included-code>
<included-code>YY</included-code>
<included-code>BB</included-code>
<included-code>WW</included-code>
<included-code>CC</included-code>
</new-item>
<new-item>
<code>BB</code>
<included-code>ZZ</included-code>
<included-code>XX</included-code>
<included-code>AA</included-code>
<included-code>CC</included-code>
<included-code>YY</included-code>
<included-code>AA</included-code>
</new-item>
<new-item>
<code>CC</code>
<included-code>VV</included-code>
<included-code>XX</included-code>
<included-code>AA</included-code>
<included-code>BB</included-code>
<included-code>WW</included-code>
<included-code>AA</included-code>
</new-item>
</result>
问题是 - 如何避免结果中出现重复值。即这是预期的:
<?xml version="1.0" encoding="UTF-8"?><result>
<new-item>
<code>AA</code>
<included-code>XX</included-code>
<included-code>BB</included-code>
<included-code>CC</included-code>
<included-code>YY</included-code>
<included-code>WW</included-code>
</new-item>
<new-item>
<code>BB</code>
<included-code>ZZ</included-code>
<included-code>XX</included-code>
<included-code>AA</included-code>
<included-code>CC</included-code>
<included-code>YY</included-code>
</new-item>
<new-item>
<code>CC</code>
<included-code>VV</included-code>
<included-code>XX</included-code>
<included-code>AA</included-code>
<included-code>BB</included-code>
<included-code>WW</included-code>
</new-item>
</result>
谢谢LarsH!看起来以下脚本可以解决问题: (我对XSLT比较陌生,所以不确定是否有更优雅的方法来保存已输出值的列表)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<result>
<xsl:apply-templates/>
</result>
</xsl:template>
<xsl:template match="item">
<new-item>
<code><xsl:value-of select="code"/></code>
<xsl:variable name="main_code"><xsl:value-of select="code"/></xsl:variable>
<xsl:call-template name="processIncludedCodes">
<xsl:with-param name="main_code" select="./code"/>
<xsl:with-param name="codes" select="./included-code"/>
</xsl:call-template>
</new-item>
</xsl:template>
<xsl:template name="processIncludedCodes">
<xsl:param name="main_code"/>
<xsl:param name="codes"/>
<xsl:param name="outputCodes"/>
<xsl:if test="$codes">
<xsl:variable name="current_code"><xsl:value-of select="$codes[1]"/></xsl:variable>
<xsl:variable name="outputCode" select="concat(':', $codes[1], ':')"/>
<xsl:if test="not(contains($outputCodes, $outputCode))">
<included-code><xsl:value-of select="$codes[1]"/></included-code>
</xsl:if>
<xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]">
<xsl:if test="not(contains($outputCodes, ./code))">
<included-code><xsl:value-of select="code"/></included-code>
</xsl:if>
</xsl:for-each>
<xsl:variable name="outputCodes2">
<xsl:for-each select="/root/item[included-code=$current_code and code!=$main_code]">
<xsl:value-of select="concat(':', code, ':')"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="newOutputCodes" select="concat($outputCodes, $outputCode, $outputCodes2)"/>
<xsl:call-template name="processIncludedCodes">
<xsl:with-param name="main_code" select="$main_code"/>
<xsl:with-param name="codes" select="$codes[position() > 1]"/>
<xsl:with-param name="outputCodes" select="$newOutputCodes"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
没有任何递归:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
<root>
<xsl:apply-templates select="item"/>
</root>
</xsl:template>
<xsl:template match="item">
<new-item>
<xsl:copy-of select="code"/>
<xsl:for-each select="included-code | /root/item[included-code = current()/included-code]/code[. != current()/included-code and . != current()/code]">
<included-code>
<xsl:value-of select="."/>
</included-code>
</xsl:for-each>
</new-item>
</xsl:template>
</xsl:stylesheet>
它会选择任何当前的<included-code>
,加上任何共同<included-code>
的项目,如果尚未包含<code>
,它会选择<?xml version="1.0" encoding="utf-8"?>
<root>
<new-item>
<code>AA</code>
<included-code>XX</included-code>
<included-code>YY</included-code>
<included-code>WW</included-code>
<included-code>BB</included-code>
<included-code>CC</included-code>
</new-item>
<new-item>
<code>BB</code>
<included-code>AA</included-code>
<included-code>ZZ</included-code>
<included-code>XX</included-code>
<included-code>YY</included-code>
<included-code>CC</included-code>
</new-item>
<new-item>
<code>CC</code>
<included-code>AA</included-code>
<included-code>BB</included-code>
<included-code>VV</included-code>
<included-code>XX</included-code>
<included-code>WW</included-code>
</new-item>
</root>
。
<强>输出:强>
{{1}}