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施加(該片段被包裹ITO單個頂部元件以獲得良好的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文檔上應用(如果我們用孩子們的值的簡單拼接,我們會錯誤地得出這樣的結論前三entry
元素是「相同」):
<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。
請注意:
該解決方案不依賴於一個entry
元素的子元素的名稱和數量,從而可以應用,如果有兩個以上的孩子,或不同數量的未知名稱的兒童。
在這裏,我們假設只有當相同的孩子具有相同的值時,所有兒童的字符串值的連接纔是相同的。
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>
說明:
對於每個entry
元素,我們產生了兒童和過程的「指紋」(FP),如果沒有它的前置兄弟entry
元素具有相同的孩子的指紋此entry
元素。
「相同」entry
元素的計數以類似的方式完成 - 對於具有相同子女FP值的任何後續兄弟entry
元素,我們輸出單個字符('1')。總計數是(「1」或多個),從而生成的字符串的字符串長度加1。
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>
說明:
正確使用xsl:for-each-group
,xsl:function
,current-group()
和string-join()
。
這就是我在找的。非常感謝 ! – user1458987
@ user1458987:不客氣。 –