2011-05-31 237 views
3

我有出現這樣的循環通過XSLT

<Data> 

<MainItem> 
<ItemGroup>Foo</ItemGroup> 
<ItemDetails>Details</ItemDetails> 
</MainItem> 

<MainItem> 
<ItemGroup>Bar</ItemGroup> 
<ItemDetails>Details</ItemDetails> 
</MainItem> 

<MainItem> 
<ItemGroup>Baz</ItemGroup> 
<ItemDetails>Details</ItemDetails> 
</MainItem> 

<OtherData> 
<ItemGroup>Foo</ItemGroup> 
<OtherDataDetails>Blah</OtherDataDetails> 
</OtherData> 

<OtherData> 
<ItemGroup>Bar</ItemGroup> 
<OtherDataDetails>BlahBlah</OtherDataDetails> 
</OtherData> 

<OtherData> 
<ItemGroup>Baz</ItemGroup> 
<OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails> 
</OtherData> 

</Data> 

我試圖改造一些XML是類似於這樣:

Foo 
- Details 
- Blah 

Bar 
- Details 
- BlahBlah 

Baz 
- Details 
- BlahBlahBlahBlahBlah 

使用XSLT 1.0。我正在通過類似於Muenchian method的方式完成分組;但我不確定如何將標籤中的數據導入到我的分組中。有小費嗎?

+0

你能展示一下你的變換嗎? – 2011-05-31 20:10:10

+0

好問題,+1。查看我的答案,找到一個完整的解決方案,它是迄今爲止最短和最有效的解決方案,不使用任何條件或'',幷包含對適當參考材料定義的主要觀點和鏈接的廣泛解釋或者教授這些基本的XSLT概念。 – 2011-06-01 03:40:55

回答

2

嘗試這樣:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" /> 

    <xsl:key name="groups" match="//ItemGroup" use="text()" /> 

    <xsl:template match="/"> 
     <Data> 
      <xsl:apply-templates 
       select="//ItemGroup[count(. | key('groups', text())[1]) = 1]" /> 
     </Data> 
    </xsl:template> 

    <xsl:template match="ItemGroup"> 
     <xsl:variable name="text" select="text()" /> 
     <Group><xsl:value-of select="$text" /></Group> 
     <xsl:for-each select="/Data/*[ItemGroup = $text]/*[contains(name(), 'Details')]"> 
      <Detail>- <xsl:value-of select="." /></Detail> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

我爲你建立一個working example

+0

+1。我喜歡這個,因爲它更通用,然後我的分組方法被應用(即使我使用'Group'來分組Detail'元素:) – 2011-05-31 20:50:30

+0

完全修改了我的答案。該方法與您的方法相同,但不使用循環。 – 2011-05-31 21:38:51

2

以下分組解決方案不使用循環,並且在ItemGroup之後處理任何其他同級元素。此外,僅使用基於MainItem的小密鑰來標識組。


XSLT 1.0撒克遜6.5.5

生產文:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="main" match="MainItem/ItemGroup" use="text()"/> 

    <xsl:template match="/Data"> 
     <xsl:apply-templates select="MainItem"/> 
    </xsl:template> 

    <xsl:template match="MainItem"> 
     <xsl:value-of select="ItemGroup"/><xsl:text>&#xA;</xsl:text> 
     <xsl:apply-templates select="ItemGroup[generate-id(.)=generate-id(key('main', current()/ItemGroup)[1])]"/> 
    </xsl:template> 

    <xsl:template match="ItemGroup"> 
     <xsl:apply-templates select="/Data/*[ItemGroup = current()]/*/following-sibling::*"/> 
     <xsl:text>&#xA;</xsl:text> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:text>- </xsl:text><xsl:value-of select="."/><xsl:text>&#xA;</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

應用在你的輸入,產生:

Foo 
- Details 
- Blah 

Bar 
- Details 
- BlahBlah 

Baz 
- Details 
- BlahBlahBlahBlahBlah 

生成XML輸出:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="main" match="MainItem/ItemGroup" use="text()"/> 

    <xsl:template match="/Data"> 
     <xsl:copy> 
      <xsl:apply-templates select="MainItem"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="MainItem"> 
     <xsl:variable name="id" select="ItemGroup"/> 
     <Group id="{$id}"> 
      <xsl:apply-templates select="ItemGroup[generate-id(.)=generate-id(key('main', current()/ItemGroup)[1])]"/> 
     </Group> 
    </xsl:template> 

    <xsl:template match="ItemGroup"> 
     <xsl:copy-of select="/Data/*[ItemGroup = current()]/*/following-sibling::*"/> 
    </xsl:template> 

</xsl:stylesheet> 

生產:

<Data> 
    <Group id="Foo"> 
     <ItemDetails>Details</ItemDetails> 
     <OtherDataDetails>Blah</OtherDataDetails> 
    </Group> 
    <Group id="Bar"> 
     <ItemDetails>Details</ItemDetails> 
     <OtherDataDetails>BlahBlah</OtherDataDetails> 
    </Group> 
    <Group id="Baz"> 
     <ItemDetails>Details</ItemDetails> 
     <OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails> 
    </Group> 
</Data> 
+0

請保持短的代碼行,以便不需要水平滾動。現在很難閱讀和理解。請爲可讀性編輯和格式化。 – 2011-06-01 03:11:07

1

這裏是僅使用模板和密鑰很短的和最有效的轉化:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:key name="kGroupByVal" match="ItemGroup" 
    use="."/> 
<xsl:key name="kNonGroupByGroup" 
    match="*[not(self::ItemGroup)]" use="../ItemGroup"/> 

<xsl:template match= 
    "ItemGroup[generate-id() 
      = 
      generate-id(key('kGroupByVal',.)[1]) 
      ] 
    "> 
<xsl:value-of select="concat('&#xA;',.)"/> 

<xsl:apply-templates mode="listGroup" 
    select="key('kNonGroupByGroup',.)"/> 
</xsl:template> 

<xsl:template match="*" mode="listGroup"> 
    <xsl:value-of select="concat('&#xA; - ', .)"/> 
</xsl:template> 
<xsl:template match="text()"/> 
</xsl:stylesheet> 

當應用於提供的XML文檔

<Data> 
    <MainItem> 
     <ItemGroup>Foo</ItemGroup> 
     <ItemDetails>Details</ItemDetails> 
    </MainItem> 
    <MainItem> 
     <ItemGroup>Bar</ItemGroup> 
     <ItemDetails>Details</ItemDetails> 
    </MainItem> 
    <MainItem> 
     <ItemGroup>Baz</ItemGroup> 
     <ItemDetails>Details</ItemDetails> 
    </MainItem> 
    <OtherData> 
     <ItemGroup>Foo</ItemGroup> 
     <OtherDataDetails>Blah</OtherDataDetails> 
    </OtherData> 
    <OtherData> 
     <ItemGroup>Bar</ItemGroup> 
     <OtherDataDetails>BlahBlah</OtherDataDetails> 
    </OtherData> 
    <OtherData> 
     <ItemGroup>Baz</ItemGroup> 
     <OtherDataDetails>BlahBlahBlahBlahBlah</OtherDataDetails> 
    </OtherData> 
</Data> 

的希望,正確的結果產生:

Foo 
- Details 
- Blah 
Bar 
- Details 
- BlahBlah 
Baz 
- Details 
- BlahBlahBlahBlahBlah 

** **說明:

  1. Muenchian grouping得到的ItemGroup不同值。

  2. Key通過ItemGroup兄弟用於索引的所有非ItemGroup元件

  3. 空模板匹配任何文本節點,以防止built-in XSLT template輸出任何文本節點。