Xslt 如何使用变量遍历节点并跳过具有相同值的重复节点
我有一个xml,比如Xslt 如何使用变量遍历节点并跳过具有相同值的重复节点,xslt,xslt-1.0,Xslt,Xslt 1.0,我有一个xml,比如 <DESIGN-FUNCTION-PROTOTYPE> <SHORT-NAME>xxx</SHORT-NAME> <TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">ABC/DEF/123</TYPE-TREF> </DESIGN-FUNCTION-PROTOTYPE> <D
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>xxx</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">ABC/DEF/123</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>yyy</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">LMN/OPQ/123</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>mmm</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">XYZ/GHY/456</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>nnn</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">AJK/UTL/456</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
而不是
123
123
456
456
一般只考虑第一个发生,跳过其余部分。
< P>假设使用XALLAN,您应该可以访问EXSLT <代码> STR:SPLIG/<代码>函数(:)假设您使用Xalan,您应该可以访问EXSLT
str:split
函数(:
要在纯XSLT 1.0中实现这一点,而不依赖于处理器特定的扩展,可以执行以下操作: XSLT1.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:key name="k1" match="DESIGN-FUNCTION-PROTOTYPE" use="substring-after(substring-after(TYPE-TREF, '/'), '/')"/>
<xsl:template match="/Root">
<root>
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE[count(. | key('k1', substring-after(substring-after(TYPE-TREF, '/'), '/'))[1]) = 1]">
<varoutput>
<xsl:value-of select="substring-after(substring-after(TYPE-TREF, '/'), '/')" />
</varoutput>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
演示:要在纯XSLT 1.0中实现这一点,而不依赖于特定于处理器的扩展,可以执行以下操作: XSLT1.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:key name="k1" match="DESIGN-FUNCTION-PROTOTYPE" use="substring-after(substring-after(TYPE-TREF, '/'), '/')"/>
<xsl:template match="/Root">
<root>
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE[count(. | key('k1', substring-after(substring-after(TYPE-TREF, '/'), '/'))[1]) = 1]">
<varoutput>
<xsl:value-of select="substring-after(substring-after(TYPE-TREF, '/'), '/')" />
</varoutput>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
演示:您已经标记了这个XSLT-1.0,但是在前面的问题中您评论说您使用的是支持XSLT 3.0的Saxon 9.8HE?您能否确认您实际使用的是哪个处理器,因为在XSLT 3.0中解决这个问题会容易得多。谢谢!我将使用XSLT-1.0(xalan)@TimC.我使用saxon online editor查看快速输出您已经标记了这个XSLT-1.0,但是在前面的问题中您评论说您使用的是支持XSLT 3.0的saxon 9.8HE?您能否确认您实际使用的是哪个处理器,因为在XSLT 3.0中解决这个问题会容易得多。谢谢!我将使用XSLT-1.0(xalan)@TimC.我使用saxon online editor查看快速输出Alan还支持
set:distinct()
,因此您不需要使用Muenchian分组。Xalan还支持set:distinct()
,因此您不需要使用Muenchian分组。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings" exclude-result-prefixes="str" version="1.0">
<xsl:key name="group" match="DESIGN-FUNCTION-PROTOTYPE/TYPE-TREF"
use="str:split(., '/')[last()]"/>
<xsl:template match="Root">
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE/TYPE-TREF[generate-id() = generate-id(key('group', str:split(., '/')[last()])[1])]">
<varoutput>
<xsl:value-of select="str:split(., '/')[last()]"/>
</varoutput>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>xxx</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">ABC/DEF/123</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>yyy</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">LMN/OPQ/123</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>mmm</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">XYZ/GHY/456</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
<DESIGN-FUNCTION-PROTOTYPE>
<SHORT-NAME>nnn</SHORT-NAME>
<TYPE-TREF TYPE="DESIGN-FUNCTION-PROTOTYPE">AJK/UTL/456</TYPE-TREF>
</DESIGN-FUNCTION-PROTOTYPE>
</Root>
<?xml version="1.0" encoding="UTF-8"?><varoutput>123</varoutput><varoutput>456</varoutput>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:str="http://exslt.org/strings"
xmlns:set="http://exslt.org/sets"
exclude-result-prefixes="exsl str set"
version="1.0">
<xsl:template match="Root">
<xsl:variable name="split-values">
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE/TYPE-TREF">
<xsl:copy-of select="str:split(., '/')[last()]"/>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="set:distinct(exsl:node-set($split-values)/node())"/>
</xsl:template>
</xsl:stylesheet>
<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:key name="k1" match="DESIGN-FUNCTION-PROTOTYPE" use="substring-after(substring-after(TYPE-TREF, '/'), '/')"/>
<xsl:template match="/Root">
<root>
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE[count(. | key('k1', substring-after(substring-after(TYPE-TREF, '/'), '/'))[1]) = 1]">
<varoutput>
<xsl:value-of select="substring-after(substring-after(TYPE-TREF, '/'), '/')" />
</varoutput>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl" >
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="k1" match="value" use="."/>
<xsl:template match="/Root">
<!-- EXTRACT VALUES -->
<xsl:variable name="values">
<xsl:for-each select="DESIGN-FUNCTION-PROTOTYPE">
<value>
<xsl:call-template name="last-token">
<xsl:with-param name="text" select="TYPE-TREF"/>
</xsl:call-template>
</value>
</xsl:for-each>
</xsl:variable>
<!-- OUTPUT -->
<root>
<xsl:for-each select="exsl:node-set($values)/value[count(. | key('k1', .)[1]) = 1]">
<varoutput>
<xsl:value-of select="." />
</varoutput>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template name="last-token">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="'/'"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="last-token">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>