[英]Stuck on grouping in XSLT 2.0
我有这样的输入文件
<items>
<item>
<id>5</id>
<name>Harry</name>
<age>18</age>
<color>blue</color>
</item>
<item>
<id>5</id>
<name>Harry</name>
<age>18</age>
<fav_food>pizza</fav_food>
</item>
<item>
<id>5</id>
<name>Harry</name>
<age>18</age>
<is_single>true</is_single>
</item>
</items>
我想将元素分组,以便文件看起来像这样
<items>
<item>
<id>5</id>
<name>Harry</name>
<age>18</age>
<color>blue</color>
<fav_food>pizza</fav_food>
<is_single>true</is_single>
</item>
</items>
编辑 - 在此链接之后进行XSLT转换( 当ID相同时,XSLT合并数据 )但这不会打印任何内容。
这是我的转换(使用XSLT 2.0) -
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="items">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="item">
<xsl:apply-templates select="@*" />
<xsl:for-each-group select="item" group-by="id">
<item>
<id><xsl:value-of select="current-grouping-key()"/></id>
<xsl:apply-templates select="current-group()" />
</item>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@*|node()[not(self::*)]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
您遇到的主要问题是您有一个匹配item元素的模板:
<xsl:template match="item">
但在此范围内,您有一个xsl:for-each-group ,它也会查找item元素
<xsl:for-each-group select="item" group-by="id">
这意味着,你正在寻找其他的项目元素,其中有没有在XML的孩子item元素。 我认为您需要将前两个模板合并为一个:
<xsl:template match="items">
<xsl:for-each-group select="item" group-by="id">
<item>
....
有一点不清楚, 项目元素中的元素将被重复。 它会永远是身份,姓名和年龄吗? 尽管这里最好是灵活的,并假设只有id才是常见元素。 我还假设如果重复两个元素(如名称 ),它将始终具有相同的值。
因此,要获取所有其他不同的非id元素,您可以对元素名称进行更多分组
<xsl:for-each-group select="current-group()/*[not(self::id)]" group-by="local-name()">
然后,在这个循环中你可以输出元素。
试试这个XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="items">
<xsl:for-each-group select="item" group-by="id">
<item>
<id><xsl:value-of select="current-grouping-key()"/></id>
<xsl:for-each-group select="current-group()/*[not(self::id)]" group-by="local-name()">
<xsl:apply-templates select="self::*" />
</xsl:for-each-group>
</item>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="@*|node()[not(self::*)]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
应用于XML时,将输出以下内容
<item>
<id>5</id>
<name>Harry</name>
<age>18</age>
<color>blue</color>
<fav_food>pizza</fav_food>
<is_single>true</is_single>
</item>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.