遍历XSLT

问题描述

| 我有一些看起来像这样的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
使用XSLT 1.0。 我目前正在通过类似于Muenchian方法方法来完成分组。但是我不确定如何将标签中的数据导入到我的分组中。有小费吗?     

解决方法

        尝试这样的事情:
<?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>
我为您建立了一个有效的例子。     ,        以下分组解决方案不使用循环,而是照顾
ItemGroup
之后的任何其他同级元素。此外,仅使用基于“ 4”的小钥匙来识别组。 Saxon 6.5.5下的XSLT 1.0 产生文字:
    <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>
    ,        这是仅使用模板和键的非常简短且最有效的转换:
<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
**说明**: Muenchian分组得到ing3ѭ的不同值。 用于通过所有非3个元素的同级索引所有非3个元素的键。 空模板与任何文本节点匹配,以防止内置XSLT模板输出任何文本节点。