从XML分组具有相同值的节点
嗨,我是Xslt / Xml的新手.
我有这样的XML: <entry> <attribute1>A</attribute1> <attribute2>B</attribute2> </entry> <entry> <attribute1>A</attribute1> <attribute2>B</attribute2> </entry> <entry> <attribute1>C</attribute1> <attribute2>D</attribute2> </entry> <entry> <attribute1>E</attribute1> <attribute2>F</attribute2> </entry> ... 我需要表输出: 一个 Attribute1 Attribute2 Qty A B 2 C D 1 E F 1 我需要你的帮助,我不知道如何计算唯一条目并将其显示为表中的一个. 我使用的是XSLT 1.0版 解决方法
I.简单的XSLT 1.0转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="kEntryByChildren" match="entry" use="."/> <xsl:template match= "entry[not(generate-id() = generate-id(key('kEntryByChildren',.)[1]))]"/> <xsl:template match="entry"> <tr> <xsl:apply-templates/> <td><xsl:value-of select="count(key('kEntryByChildren',.))"/></td> </tr> </xsl:template> <xsl:template match="entry/*"> <td><xsl:value-of select="."/></td> </xsl:template> <xsl:template match="/*"> <table> <xsl:apply-templates/> </table> </xsl:template> </xsl:stylesheet> 当应用于提供的XML时(片段被包装到单个顶部元素以获得格式良好的XML文档): <t> <entry> <attribute1>A</attribute1> <attribute2>B</attribute2> </entry> <entry> <attribute1>A</attribute1> <attribute2>B</attribute2> </entry> <entry> <attribute1>C</attribute1> <attribute2>D</attribute2> </entry> <entry> <attribute1>E</attribute1> <attribute2>F</attribute2> </entry> </t> 产生想要的,正确的结果: <table> <tr> <td>A</td> <td>B</td> <td>2</td> </tr> <tr> <td>C</td> <td>D</td> <td>1</td> </tr> <tr> <td>E</td> <td>F</td> <td>1</td> </tr> </table> 当应用于这个棘手的XML文档时(如果我们使用子级值的简单连接,我们会错误地断定前三个条目元素是“相同的”): <t> <entry> <attribute1>AB</attribute1> <attribute2>C</attribute2> </entry> <entry> <attribute1>A</attribute1> <attribute2>BC</attribute2> </entry> <entry> <attribute1>A</attribute1> <attribute2>BC</attribute2> </entry> <entry> <attribute1>C</attribute1> <attribute2>D</attribute2> </entry> <entry> <attribute1>E</attribute1> <attribute2>F</attribute2> </entry> </t> 产生了正确的结果: <table> <tr> <td>AB</td> <td>C</td> <td>1</td> </tr> <tr> <td>A</td> <td>BC</td> <td>2</td> </tr> <tr> <td>C</td> <td>D</td> <td>1</td> </tr> <tr> <td>E</td> <td>F</td> <td>1</td> </tr> </table> 说明: 正确使用Muenchian grouping method. 请注意: >此解决方案不依赖于条目元素的子名称和子项数,因此可以应用于具有两个以上子项或具有未知事先名称的不同数量的子项的情况. II.完整的XSLT 1.0解决方案: 如果无法保证上面的假设2.这是一个可能的XSLT 1.0解决方案: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="entry"> <xsl:variable name="vChildrenFp"> <xsl:for-each select="*"> <xsl:value-of select="concat(.,'+')"/> </xsl:for-each> </xsl:variable> <xsl:variable name="vPrecedingSame"> <xsl:for-each select="preceding-sibling::entry"> <xsl:variable name="vthisFP"> <xsl:for-each select="*"> <xsl:value-of select="concat(.,'+')"/> </xsl:for-each> </xsl:variable> <xsl:if test="$vthisFP = $vChildrenFp">1</xsl:if> </xsl:for-each> </xsl:variable> <xsl:if test="not(string($vPrecedingSame))"> <xsl:variable name="vFollowingSame"> <xsl:for-each select="following-sibling::entry"> <xsl:variable name="vthisFP"> <xsl:for-each select="*"> <xsl:value-of select="concat(.,'+')"/> </xsl:for-each> </xsl:variable> <xsl:if test="$vthisFP = $vChildrenFp">1</xsl:if> </xsl:for-each> </xsl:variable> <tr> <xsl:apply-templates/> <td><xsl:value-of select="string-length($vFollowingSame)+1"/></td> </tr> </xsl:if> </xsl:template> <xsl:template match="entry/*"> <td><xsl:value-of select="."/></td> </xsl:template> <xsl:template match="/*"> <table> <xsl:apply-templates/> </table> </xsl:template> </xsl:stylesheet> 当应用于同一XML文档(上面)时,会产生相同的正确结果: <table> <tr> <td>A</td> <td>B</td> <td>2</td> </tr> <tr> <td>C</td> <td>D</td> <td>1</td> </tr> <tr> <td>E</td> <td>F</td> <td>1</td> </tr> </table> 说明: >对于每个条目元素,我们生成其子元素的“指纹”(FP),并在其前一个兄弟条目元素没有相同子元素的指纹时处理该条目元素. III. XSLT 2.0解决方案: <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my" exclude-result-prefixes="my xs"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="pExoticString" select="'+'"/> <xsl:template match="/*"> <table> <xsl:for-each-group select="entry" group-by="my:fingerprint(.)"> <tr> <xsl:apply-templates/> <td><xsl:value-of select="count(current-group())"/></td> </tr> </xsl:for-each-group> </table> </xsl:template> <xsl:template match="entry/*"> <td><xsl:value-of select="."/></td> </xsl:template> <xsl:function name="my:fingerprint" as="xs:string"> <xsl:param name="pParent" as="element()"/> <xsl:sequence select="string-join($pParent/*,$pExoticString)"/> </xsl:function> </xsl:stylesheet> 这个简单的解决方案很容易处理复杂的情应用于最后一个XML文档时,会生成所需的正确结果: <table> <tr> <td>AB</td> <td>C</td> <td>1</td> </tr> <tr> <td>A</td> <td>BC</td> <td>2</td> </tr> <tr> <td>C</td> <td>D</td> <td>1</td> </tr> <tr> <td>E</td> <td>F</td> <td>1</td> </tr> </table> 说明: 正确使用 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |