我需要根据属性值通过xslt合并两个复杂元素节点,即例如当id = 1时,需要合并其各自的名称值元素。所以对于id = 2,3 ..等等
<?xml version="1.0" encoding="UTF-8"?>
<xrefStore>
<xrefData>
<entityData>
<entry id="1">
<keyValue name="A" value=" "/>
<keyValue name="B" value=" "/>
<keyValue name="C" value=" "/>
</entry>
<entry id="2">
<keyValue name="A" value=" "/>
<keyValue name="B" value=" "/>
<keyValue name="c" value=" "/>
<keyValue name="D" value=" "/>
<keyValue name="E" value=" "/>
</entry>
<entry id="1">
<keyValue name="D" value=" "/>
<keyValue name="E" value=" "/>
</entry>
</xrefStore>
</xrefData>
最终输出应如下,
<?xml version="1.0"?>
<root>
<set id="1">
<nameValuePair>
<name>A</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>B</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>C</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>D</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>E</name>
<value> </value>
</nameValuePair>
</set>
<set id="2">
<nameValuePair>
<name>A</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>B</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>C</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>D</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>E</name>
<value> </value>
</nameValuePair>
</set>
</root>
我已经尝试了下面的代码,但它没有基于id合并。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:for-each select="xrefStore/xrefData/entityData/entity/entry">
<set >
<xsl:attribute name="id">
<xsl:value-of select="current()/@id" />
</xsl:attribute>
<xsl:for-each select="current()/keyValue">
<nameValuePair>
<name>
<xsl:value-of select="current()/@name" />
</name>
<value>
<xsl:value-of select="current()/@value" />
</value>
</nameValuePair>
</xsl:for-each>
</set>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
任何形式的帮助表示赞赏。
我在这里找到了类似的答案,Merge XML nodes using XSLT
但我不明白他们实施的概念。
虽然这个问题已经有几个月的历史了,但是考虑发布一个答案,以便它可能对其他可能碰巧遇到这个问题的人有用。
XSLT 1.0解决方案
需要声明一个密钥,该密钥将用于对相同节点进行分组。在示例中,需要在id
元素的<entry>
属性上进行分组。
<xsl:key name="kId" match="entry" use="@id" />
需要对所有<entry>
节点进行循环,其唯一标识符(由generate-id()
函数返回)与密钥的唯一标识符匹配。
<xsl:for-each select="entry[generate-id() = generate-id(key('kId', @id)[1])]">
最后循环遍历分组键中的所有<keyValue>
节点以获得所需结果。
<xsl:for-each select="key('kId',@id)/keyValue">
使用版本1.0
的完整XSL如下所示。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- declare key to group nodes -->
<xsl:key name="kId" match="entry" use="@id" />
<xsl:template match="entityData">
<root>
<!-- loop through the grouped keys -->
<xsl:for-each select="entry[generate-id() = generate-id(key('kId', @id)[1])]">
<set>
<xsl:attribute name="id">
<xsl:value-of select="@id" />
</xsl:attribute>
<!-- loop through the elements of the key -->
<xsl:for-each select="key('kId',@id)/keyValue">
<nameValuePair>
<name>
<xsl:value-of select="@name" />
</name>
<value>
<xsl:value-of select="@value" />
</value>
</nameValuePair>
</xsl:for-each>
</set>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0解决方案
2.0版使用grouping
功能为<xsl:for-each-group>
提供了一种更简单的方法。下面是XSL。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="entityData">
<root>
<!-- loop through 'entry' groups grouped by 'id' attribute -->
<xsl:for-each-group select="entry" group-by="@id">
<set>
<xsl:attribute name="id">
<xsl:value-of select="current-grouping-key()" />
</xsl:attribute>
<!-- loop through current group for all 'keyValue' elements -->
<xsl:for-each select="current-group()/keyValue">
<nameValuePair>
<name>
<xsl:value-of select="@name" />
</name>
<value>
<xsl:value-of select="@value" />
</value>
</nameValuePair>
</xsl:for-each>
</set>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
两种解决方案都将输入XML转换为所需的输出
<root>
<set id="1">
<nameValuePair>
<name>A</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>B</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>C</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>D</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>E</name>
<value> </value>
</nameValuePair>
</set>
<set id="2">
<nameValuePair>
<name>A</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>B</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>c</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>D</name>
<value> </value>
</nameValuePair>
<nameValuePair>
<name>E</name>
<value> </value>
</nameValuePair>
</set>
</root>