2009-11-18 109 views
2

我想在我的XSLT中使用Muenchian分組來分組匹配的節點,但我只想在父節點內分組,而不是跨整個源XML文檔。Muenchian分組 - 在一個節點內的組,而不是在整個文檔中

鑑於XSLT和XML如下(道歉的我的樣本代碼的長度):

XSLT

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
<xsl:output method="html" indent="yes"/> 

<xsl:key name="contacts-by-surname" match="contact" use="surname" /> 
<xsl:template match="records"> 
    <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]"> 
    <xsl:sort select="surname" /> 
    <xsl:value-of select="surname" />,<br /> 
    <xsl:for-each select="key('contacts-by-surname', surname)"> 
    <xsl:sort select="forename" /> 
    <xsl:value-of select="forename" /> (<xsl:value-of select="title" />)<br /> 
    </xsl:for-each> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

XML

<root> 
<records> 
    <contact id="0001"> 
    <title>Mr</title> 
    <forename>John</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0002"> 
    <title>Dr</title> 
    <forename>Amy</forename> 
    <surname>Jones</surname> 
    </contact> 
    <contact id="0003"> 
    <title>Mrs</title> 
    <forename>Mary</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0004"> 
    <title>Ms</title> 
    <forename>Anne</forename> 
    <surname>Jones</surname> 
    </contact> 
    <contact id="0005"> 
    <title>Mr</title> 
    <forename>Peter</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0006"> 
    <title>Dr</title> 
    <forename>Indy</forename> 
    <surname>Jones</surname> 
    </contact> 
</records> 
<records> 
    <contact id="0001"> 
    <title>Mr</title> 
    <forename>James</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0002"> 
    <title>Dr</title> 
    <forename>Mandy</forename> 
    <surname>Jones</surname> 
    </contact> 
    <contact id="0003"> 
    <title>Mrs</title> 
    <forename>Elizabeth</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0004"> 
    <title>Ms</title> 
    <forename>Sally</forename> 
    <surname>Jones</surname> 
    </contact> 
    <contact id="0005"> 
    <title>Mr</title> 
    <forename>George</forename> 
    <surname>Smith</surname> 
    </contact> 
    <contact id="0006"> 
    <title>Dr</title> 
    <forename>Harry</forename> 
    <surname>Jones</surname> 
    </contact> 
</records> 
</root> 

RESULT

Jones, 
Amy (Dr) 
Anne (Ms) 
Harry (Dr) 
Indy (Dr) 
Mandy (Dr) 
Sally (Ms) 

Smith, 
Elizabeth (Mrs) 
George (Mr) 
James (Mr) 
John (Mr) 
Mary (Mrs) 
Peter (Mr) 

我怎麼組的每個<records>內實現這一結果:

Jones, 
Amy (Dr) 
Anne (Ms) 
Indy (Dr) 

Smith, 
John (Mr) 
Mary (Mrs) 
Peter (Mr) 

Jones, 
Harry (Dr) 
Mandy (Dr) 
Sally (Ms) 

Smith, 
Elizabeth (Mrs) 
George (Mr) 
James (Mr) 
+1

+1好問題 – 2009-11-18 05:18:35

+0

克里斯蒂安,在你想要的結果中,姓氏沒有在姓氏內排序。我假設他們應該是因爲你明確地在你的xslt的forename排序。 – 2009-11-18 05:41:19

+0

有關訂購的好處 - 已更新問題以在結果中包含已排序的名稱。 – kristian 2009-11-18 05:59:50

回答

6

我花了一些時間......我正要放棄,但仍繼續:)

的缺點關鍵功能是生成的密鑰將始終用於整個xml。因此,您應該連接密鑰中的其他信息以使其更加具體。在例如在下面,我將連接記錄節點的位置,以便爲每個記錄獲得不同姓氏的密鑰。

這裏的XSLT:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="html" indent="yes"/> 
    <xsl:key name="distinct-surname" match="contact" use="concat(generate-id(..), '|', surname)"/> 
    <xsl:template match="records"> 
    <xsl:for-each select="contact[generate-id() = generate-id(key('distinct-surname', concat(generate-id(..), '|', surname))[1])]"> 
     <xsl:sort select="surname" /> 
     <xsl:value-of select="surname" />,<br /> 
     <xsl:for-each select="key('distinct-surname', concat(generate-id(..), '|', surname))"> 
     <xsl:sort select="forename" /> 
     <xsl:value-of select="forename" /> (<xsl:value-of select="title" />)<br /> 
     </xsl:for-each> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

這是結果:

Jones, 
Amy (Dr) 
Anne (Ms) 
Indy (Dr) 
Smith, 
John (Mr) 
Mary (Mrs) 
Peter (Mr) 
Jones, 
Harry (Dr) 
Mandy (Dr) 
Sally (Ms) 
Smith, 
Elizabeth (Mrs) 
George (Mr) 
James (Mr) 

請注意,結果在forenames排序了。如果你不希望它forenames排序,你需要刪除線<xsl:sort select="forename" />

+0

很好的回答和解釋。謝謝! – kristian 2009-11-18 06:05:00

+0

這就是我會做的+1。我提出了一個小小的改變:使用'concat(generate-id(..),'|',surname)'而不是'concat(count(parent :: */preceding-sibling :: *),surname)'。由於額外的分隔符char,它更短,更高效並且更安全。 – Tomalak 2009-11-18 10:56:13

+0

Tomalak,我根據您的建議編輯了xslt。謝謝:) – 2009-11-18 12:48:55

3

有更簡單的方法,通過添加謂詞,確保比參與測試MUENCH接觸的電流記錄孩子。

<xsl:key name="contacts-by-surname" match="contact" use="surname" /> 
<xsl:template match="records"> 
    <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[generate-id(parent::records) = generate-id(current())][1]) = 1]"> 
    <xsl:sort select="surname" /> 
    <xsl:value-of select="surname" />,<br /> 
    <xsl:for-each select="key('contacts-by-surname', surname)[generate-id(parent::records) = generate-id(current()/parent::records)]"> 
    <xsl:sort select="forename" /> 
    <xsl:value-of select="forename" /> (<xsl:value-of select="title" />)<br /> 
    </xsl:for-each> 
    </xsl:for-each> 
</xsl:template> 
+0

它可能更簡單,但效率也不高。在最壞的情況下,我會說'contact [generate-id()= generate-id(... [...])]'是O(n²),而@Rashmi Pandit的'contact [generate-id()= generate-id (...)]'是O(n)。 – Tomalak 2009-11-18 11:12:12

+0

也許效率較低,但我認爲更強大。將字符串連接成複合鍵意味着分隔符字符串不會出現在任何使用的字符串中。我更喜歡最快的確定性行爲。 :) – Erlock 2009-11-18 13:46:14

+0

嗯...我可以想象一種方式,id值是不明確的(id'「key-30」',value'「0」'vs.id'「key-300」,value'「」'),但是對於id-separator-value(它會是''id-30 | 0「'''id-300 |」')?恕我直言,值的分隔符的存在是不相關的。我錯過了什麼嗎? – Tomalak 2009-11-18 15:10:14

相關問題