循环 XSLT

发布于 2024-11-11 15:39:34 字数 1169 浏览 0 评论 0原文

我有一些看起来像这样的 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 方法 的操作来完成分组;但我不确定如何将标签中的数据引入我的分组中。有什么建议吗?

I've got some XML that appears like this

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

What I'm trying to transform is something similar to this:

Foo
- Details
- Blah

Bar
- Details
- BlahBlah

Baz
- Details
- BlahBlahBlahBlahBlah

using XSLT 1.0.

I'm currently accomplishing the grouping by doing something similar to the Muenchian method; but I'm not sure how to bring in the data from the tags into my grouping. Any tips?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无所的.畏惧 2024-11-18 15:39:34

尝试这样的操作:

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

我为您设置了一个工作示例

Try something like this:

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

I set up a working example for you.

原谅我要高飞 2024-11-18 15:39:34

以下分组解决方案不使用循环并处理 ItemGroup 后面的任何其他同级元素。此外,仅使用基于 MainItem 的小密钥来识别组。


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>
</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>
</xsl:text>
    </xsl:template>

    <xsl:template match="*">
        <xsl:text>- </xsl:text><xsl:value-of select="."/><xsl:text>
</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>

The following grouping solution does not use loops and take care of any other sibling element following the ItemGroup. Moreover only a small key based on MainItem is used to identify the groups.


XSLT 1.0 under Saxon 6.5.5

Producing text:

    <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>
</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>
</xsl:text>
    </xsl:template>

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

</xsl:stylesheet>

Applied on your input, produces:

 Foo
- Details
- Blah

Bar
- Details
- BlahBlah

Baz
- Details
- BlahBlahBlahBlahBlah

Producing XML output:

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

produces:

<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>
不醒的梦 2024-11-18 15:39:34

这是一个非常简短且最有效的转换,仅使用模板和键:

<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('
',.)"/>

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

 <xsl:template match="*" mode="listGroup">
  <xsl:value-of select="concat('
 - ', .)"/>
 </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>

生成所需的正确结果:< /strong>

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

** 说明**:

  1. 慕尼黑分组 获取 ItemGroup 的不同值。

  2. Key 用于索引所有非ItemGroup 元素通过其 ItemGroup 同级元素。

  3. 匹配任何文本节点的空模板,以防止内置 XSLT模板输出任何文本节点。

Here is a very short and most efficient transformation that uses only templates and keys:

<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('
',.)"/>

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

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

When applied on the provided XML document:

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

the wanted, correct result is produced:

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

** Explanation**:

  1. Muenchian grouping to get the distinct values of ItemGroup.

  2. Key used to index all non-ItemGroup elements by their ItemGroup sibling.

  3. Empty template matching any text node to prevent the built-in XSLT template to output any text node.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文