循环通过XSLT

循环通过XSLT

问题描述:

我有出现这样的循环通过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

尝试这样:

<?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

以下分组解决方案不使用循环,并且在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

这里是仅使用模板和密钥很短的和最有效的转化:

<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输出任何文本节点。