XML 通过根据某个值对标签进行分组,使用 XSLT 进行转换
XML transformation using XSLT by grouping the tags based on some value
我正在尝试通过对标签进行分组来创建新标签来转换一个 XML。喜欢将具有相同父值的项目分组。
<root>
<item id="100">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="101">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="102">
<properties>
<property attribute-id="parent">11</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="103">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="104">
<properties>
<property attribute-id="parent">11</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
</root>
新标签应该是:
<item id = "10">
<childs>
<child id="100" />
<child id="101" />
<child id="102" />
</childs>
</item>
<item id = "11">
<childs>
<child id="104" />
<child id="105" />
</childs>
</item>
这可以用 XSLT 实现吗?
这如何在 XSLT 中完成?
编辑初始 post 当标签为属性格式时,我遇到了一些问题。尝试更新第一个解决方案,但属性形式导致许多问题。
您可以使用 XSLT-1.0 方法 Muenchian Grouping 来实现。如果你搜索 SO,你会发现很多例子。应用此方法,您的样式表可能如下所示(我在源代码 XML 周围添加了一个假设的 <root>
元素以使其 格式正确 ):
外部 xsl:for-each
的 xsl:key
和 select
表达式确实实现了 Muenchian 分组。循环内部应该有点不言自明。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="id" match="item" use="properties/property[@attribute-id='parent']" />
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="item[generate-id() = generate-id(key('id',properties/property[@attribute-id='parent'])[1])]">
<item id="{parent}">
<childs>
<xsl:for-each select="key('id',properties/property[@attribute-id='parent'])">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果您可以使用 XSLT-2.0 或更高版本,您可以像这样使用 xsl:for-each-group
:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each-group select="item" group-by="properties/property[@attribute-id='parent']">
<item id="{parent}">
<childs>
<xsl:for-each select="current-group()">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它稍微简单一些,但功能相同。
它的输出,在这两种情况下,都是:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="">
<childs>
<child id="100"/>
<child id="101"/>
<child id="103"/>
</childs>
</item>
<item id="">
<childs>
<child id="102"/>
<child id="104"/>
</childs>
</item>
</root>
这不是您想要的,但我猜您示例的最后一个 child
ID 是错误的。
我正在尝试通过对标签进行分组来创建新标签来转换一个 XML。喜欢将具有相同父值的项目分组。
<root>
<item id="100">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="101">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="102">
<properties>
<property attribute-id="parent">11</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="103">
<properties>
<property attribute-id="parent">10</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
<item id="104">
<properties>
<property attribute-id="parent">11</property>
</properties>
<properties>
<property attribute-id="amount">1.1</property>
</properties>
</item>
</root>
新标签应该是:
<item id = "10">
<childs>
<child id="100" />
<child id="101" />
<child id="102" />
</childs>
</item>
<item id = "11">
<childs>
<child id="104" />
<child id="105" />
</childs>
</item>
这可以用 XSLT 实现吗?
这如何在 XSLT 中完成?
编辑初始 post 当标签为属性格式时,我遇到了一些问题。尝试更新第一个解决方案,但属性形式导致许多问题。
您可以使用 XSLT-1.0 方法 Muenchian Grouping 来实现。如果你搜索 SO,你会发现很多例子。应用此方法,您的样式表可能如下所示(我在源代码 XML 周围添加了一个假设的 <root>
元素以使其 格式正确 ):
外部 xsl:for-each
的 xsl:key
和 select
表达式确实实现了 Muenchian 分组。循环内部应该有点不言自明。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="id" match="item" use="properties/property[@attribute-id='parent']" />
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="item[generate-id() = generate-id(key('id',properties/property[@attribute-id='parent'])[1])]">
<item id="{parent}">
<childs>
<xsl:for-each select="key('id',properties/property[@attribute-id='parent'])">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果您可以使用 XSLT-2.0 或更高版本,您可以像这样使用 xsl:for-each-group
:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each-group select="item" group-by="properties/property[@attribute-id='parent']">
<item id="{parent}">
<childs>
<xsl:for-each select="current-group()">
<child id="{@id}" />
</xsl:for-each>
</childs>
</item>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它稍微简单一些,但功能相同。
它的输出,在这两种情况下,都是:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="">
<childs>
<child id="100"/>
<child id="101"/>
<child id="103"/>
</childs>
</item>
<item id="">
<childs>
<child id="102"/>
<child id="104"/>
</childs>
</item>
</root>
这不是您想要的,但我猜您示例的最后一个 child
ID 是错误的。