如何用XSLT 1.0合并XML中跨message的同ID object元素?
用XSLT 1.0合并两个message中的同ID object元素并整合内容
我查了很多XSLT合并与分组的文章,但没找到匹配我场景的案例。作为偶尔开发的人,我觉得XSLT的合并/分组操作挺复杂,尤其是嵌套XML里有多个"数组"的情况。有一篇类似的文章《XML merge nodes with XSLT》,但它是在单一场景内分组,不是跨不同场景分组。
我的需求:
合并根节点为messages的XML文件中的两个message元素(固定两个)。合并后的message里,需要基于object元素的ID进行合并,只保留ID在两个message中都存在的object,并整合它们的所有子元素。
初始XML
<?xml version="1.0" encoding="UTF-8"?> <messages> <message> <submessage> <object> <ID>991</ID> <Extra>ABC</Extra> </object> <object> <ID>992</ID> <Extra>BCD</Extra> </object> <object> <ID>993</ID> <Extra>CDE</Extra> </object> </submessage> </message> <message> <submessage> <object> <ID>992</ID> <Name>Marcel</Name> <Description>XXX</Description> </object> <object> <ID>993</ID> <Name>Peter</Name> <Description>YYY</Description> </object> <object> <ID>994</ID> <Name>Lola</Name> <Description>ZZZ</Description> </object> </submessage> </message> </messages>
期望结果XML
<?xml version="1.0" encoding="UTF-8"?> <messages> <message> <submessage> <object> <ID>992</ID> <Name>Marcel</Name> <Description>XXX</Description> <Extra>BCD</Extra> </object> <object> <ID>993</ID> <Name>Peter</Name> <Description>YYY</Description> <Extra>CDE</Extra> </object> </submessage> </message> </messages>
说明:仅保留两个message中ID匹配的object元素,比如ID为991和994的object会被删除,ID为992和993的object会被保留并整合所有内部元素。每个message下仅存在一个submessage元素。
XSLT 1.0解决方案
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 按ID分组所有object元素 --> <xsl:key name="object-by-id" match="object" use="ID"/> <!-- 匹配根节点messages --> <xsl:template match="/messages"> <messages> <message> <submessage> <!-- 筛选出在两个message中都存在的object分组(分组大小为2) --> <xsl:for-each select="message/submessage/object[count(key('object-by-id', ID)) = 2][generate-id() = generate-id(key('object-by-id', ID)[1])]"> <object> <!-- 复制当前分组下所有object的子元素 --> <xsl:copy-of select="key('object-by-id', ID)/*"/> </object> </xsl:for-each> </submessage> </message> </messages> </xsl:template> </xsl:stylesheet>
代码说明
- Muenchian分组:通过
<xsl:key>定义按ID分组所有object元素,这是XSLT 1.0中实现高效分组的标准方法。 - 筛选匹配ID:使用
count(key('object-by-id', ID)) = 2确保只保留在两个message中都存在的object(因为每个匹配的ID恰好对应两个object节点,分别来自两个message)。 - 去重分组:
generate-id() = generate-id(key('object-by-id', ID)[1])确保每个ID只处理一次,避免重复创建object节点。 - 整合子元素:通过
<xsl:copy-of select="key('object-by-id', ID)/*"将同一ID下所有object的子元素复制到新的object节点中,实现内容整合。
内容的提问来源于stack exchange,提问作者Robin Haes
相关产品推荐
相关产品推荐

