通过基于某些值对标签进行分组来使用XSLT进行XML转换

时间:2019-01-24 20:06:00

标签: xml xslt simple-xml-converter

我正在尝试通过将标签分组来创建新标签来转换一种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中完成?

编辑初始帖子,当标签为属性格式时,我遇到了一些问题。试图更新第一个解决方案,但属性形式引起许多问题。

1 个答案:

答案 0 :(得分:0)

您可以使用 XSLT-1.0 方法 Muenchian分组来实现。如果您搜索SO,则会发现很多示例。应用此方法,您的样式表应如下所示(我在源XML的周围添加了一个假设的<root>元素,以使其格式正确):

外部xsl:key的{​​{1}}和select表达式确实实现了 Muenchian分组。循环的内部应该是不言自明的。

xsl:for-each

如果您可以使用 XSLT-2.0 或更高版本,则可以像这样使用<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>

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> 个ID是错误的。