如何用XSLT 1.0合并XML中@Name相同的Designation父标签
使用XSLT 1.0合并同名@Name属性的Designation标签
给定如下XML结构,需要将所有@Name属性值相同的<Designation>父标签合并为一个,并整合所有子标签(重复的子标签保留所有实例,仅重复的<Designation>子标签保留一个):
<?xml version="1.0" encoding="UTF-8"?> <Nodes> <Designation Name="Minimum opening time"> <Designation>Minimum opening time</Designation> <Car_No>8nn2</Car_No> <Sys>RSC</Sys> <Main>SDOR</Main> <Sub>SDOR</Sub> <Side>B1</Side> <Byte_N_x00B0>2</Byte_N_x00B0> <_x0030>X</_x0030> <_x0031>X</_x0031> <_x0032>X</_x0032> <_x0033>X</_x0033> <_x0034>X</_x0034> <_x0035>X</_x0035> <_x0036>X</_x0036> <_x0037>X</_x0037> <Car>2</Car> <Loc>1B</Loc> <Notes>unit time = 100 ms</Notes> </Designation> <Designation Name="DATE: Month number"> <Designation>DATE: Month number</Designation> <Byte_N_x00B0>4</Byte_N_x00B0> <_x0030>apple</_x0030> <_x0031></_x0031> <_x0032></_x0032> <_x0033></_x0033> <_x0034></_x0034> <_x0035></_x0035> <_x0036>orange</_x0036> <_x0037>grapes</_x0037> <Notes>From 1 to 12 coded by 4 bits</Notes> </Designation> <Designation Name="DATE: Month number"> <Designation>DATE: Month number</Designation> <Byte_N_x00B0>5</Byte_N_x00B0> <_x0030>pomegranate</_x0030> <_x0031>tomato</_x0031> <_x0032></_x0032> <_x0033></_x0033> <_x0034></_x0034> <_x0035></_x0035> <_x0036></_x0036> <_x0037></_x0037> <Notes> </Notes> </Designation> </Nodes>
合并后需得到如下XML:
<?xml version="1.0" encoding="UTF-8"?> <Nodes> <Designation Name="Minimum opening time"> <Designation>Minimum opening time</Designation> <Car_No>8nn2</Car_No> <Sys>RSC</Sys> <Main>SDOR</Main> <Sub>SDOR</Sub> <Side>B1</Side> <Byte_N_x00B0>2</Byte_N_x00B0> <_x0030>X</_x0030> <_x0031>X</_x0031> <_x0032>X</_x0032> <_x0033>X</_x0033> <_x0034>X</_x0034> <_x0035>X</_x0035> <_x0036>X</_x0036> <_x0037>X</_x0037> <Car>2</Car> <Loc>1B</Loc> <Notes>unit time = 100 ms</Notes> </Designation> <Designation Name="DATE: Month number"> <Designation>DATE: Month number</Designation> <Byte_N_x00B0>4</Byte_N_x00B0> <Byte_N_x00B0>5</Byte_N_x00B0> <_x0030>apple</_x0030> <_x0030>pomegranate</_x0030> <_x0031>tomato</_x0031> <_x0032></_x0032> <_x0033></_x0033> <_x0034></_x0034> <_x0035></_x0035> <_x0036>orange</_x0036> <_x0037>grapes</_x0037> <Notes>From 1 to 12 coded by 4 bits</Notes> <Notes> </Notes> </Designation> </Nodes>
XSLT 1.0实现代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 输出保留XML声明和缩进格式 --> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <!-- 匹配根节点,复制整体结构 --> <xsl:template match="/Nodes"> <xsl:copy> <!-- 定义分组键:按Designation标签的@Name属性分组 --> <xsl:key name="designation-group" match="Designation" use="@Name"/> <!-- 遍历每个分组的第一个节点(作为合并后的标签模板) --> <xsl:for-each select="Designation[generate-id() = generate-id(key('designation-group', @Name)[1])]"> <!-- 创建合并后的Designation标签,保留原Name属性 --> <Designation Name="{@Name}"> <!-- 复制分组内第一个节点的Designation子标签(仅保留一个,因为同组内容一致) --> <xsl:copy-of select="Designation"/> <!-- 遍历同组所有节点,复制除Designation外的所有子标签 --> <xsl:for-each select="key('designation-group', @Name)"> <xsl:copy-of select="*[not(local-name()='Designation')]"/> </xsl:for-each> </Designation> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- Muenchian分组机制:XSLT 1.0无原生分组功能,通过
<xsl:key>定义分组规则,将所有<Designation>标签按@Name属性归类。 - 分组筛选:通过
generate-id() = generate-id(key('designation-group', @Name)[1])定位每个分组的第一个节点,作为合并后标签的容器。 - 子标签整合:
- 单独复制分组内第一个节点的
<Designation>子标签,避免重复冗余。 - 遍历同组所有节点,复制其余所有子标签,包括重复标签(如
<Byte_N_x00B0>)和空标签,完全匹配需求中的整合逻辑。
- 单独复制分组内第一个节点的
- 格式保留:通过
<xsl:output>配置输出带缩进的XML,保持结构可读性。
内容的提问来源于stack exchange,提问作者Smiley
相关产品推荐
相关产品推荐

