使用XSLT根据属性id合并节点



我在合并节点并根据属性值将它们放入新节点时遇到了问题。我的源XML看起来像-

<?xml version='1.0' encoding='UTF-8'?>
<Rep><RepData>
<Row>
<Field name="ID">A</Field>
<Field name="CName">Angle</Field>
<Field name="GPL">A-G</Field>
</Row>
<Row>
<Field name="ID">J-A</Field>
<Field name="CName">J-A-Ang</Field>
<Field name="GPL">GPL_A-J</Field>
</Row>
<Row>
<Field name="ID">J-U</Field>
<Field name="CName">J-U-Ang</Field>
<Field name="GPL">GPL_A-U</Field>
</Row>
<Row>
<Field name="ID">J-I</Field>
<Field name="CName">J-I-Ang</Field>
<Field name="GPL">GPL_A-I</Field>
</Row>
<Row>
<Field name="ID">M</Field>
<Field name="CName">Ma</Field>
<Field name="GPL">A-M</Field>
</Row>
</RepData>
</Rep>

我使用的XSLT如下-

<xsl:template match="/Rep/Report">
<ccs>
<xsl:for-each-group select="Row" group-by="Field[@name='ID']">
<ccwc>
<xsl:variable name="ref">
<xsl:value-of select="current-grouping-key()"/>
</xsl:variable>
<xsl:attribute name="id"><xsl:value-of select="$ref"/>
</xsl:attribute>
<name>
<xsl:if test="string-length(Field[@name='CName']) != 0">
<xsl:value-of select="Field[@name='CName']"/>
</xsl:if>
<xsl:if test="string-length(Field[@name='CName']) =0">
Unknown
</xsl:if>
</name>
<cccs>
<xsl:for-each-group select="current-group()" group-by="Field[@name='GPL']">
<ccc>
<xsl:variable name="childRef">
<xsl:value-of select="current-grouping-key()"/>
</xsl:variable>
<xsl:variable name="fullRef">
<xsl:value-of select="$ref,$childRef"></xsl:value-of>
</xsl:variable>
<xsl:attribute name="id">
<xsl:value-of select="$fullRef"/>
</xsl:attribute>
<name>
<xsl:value-of select="current-grouping-key()"/>
</name>
</ccc>
</xsl:for-each-group>
</cccs>
</ccwc>
</xsl:for-each-group>
</ccs>
</xsl:template>
</xsl:transform>

使用上面的XSLT,我得到的输出XML是-

<ccwc id="A">
<name>Angle</name>
<cccs>
<ccc id="A A-G">
<name>A-G</name>
</ccc>
</cccs>
</ccwc>
<ccwc id="J-A">
<name>J-A-Ang</name>
<cccs>
<ccc id="J-A A-J">
<name>A-J</name>
</ccc>
</cccs>
</ccwc>
<ccwc id="J-U">
<name>J-U-Ang</name>
<cccs>
<ccc id="J-U A-U">
<name>A-U</name>
</ccc>
</cccs>
</ccwc>
<ccwc id="J-I">
<name>J-I-Ang</name>
<cccs>
<ccc id="J-I A-I">
<name>A-I</name>
</ccc>
</cccs>
</ccwc>
<ccwc id="M">
<name>Ma</name>
<cccs>
<ccc id="M A-M">
<name>A-M</name>
</ccc>
</cccs>
</ccwc>
</ccs>

我想合并<Field name="ID">以'J'开头的节点,并将它们全部放在一个新节点下,层次结构的其余部分应保持不变。我期望的XML应该看起来像-

<ccwc id="A">
<name>Angle</name>
<cccs>
<ccc id="A A-G">
<name>A-G</name>
</ccc>
</cccs>
</ccwc>
<ccwc id="1-J">
<name>One J</name>
<cccs>
<ccc id ="1-J_J-A">
<name>J-A-Ang</name>
<cccs>
<ccc id="1-J_J-A_GPL_A-J">
<name>GPL_A-J</name>
</ccc>
</cccs>
</ccc>
<ccc id ="1-J_J-U">
<name>J-U-Ang</name>
<cccs>
<ccc id="1-J_J-U_GPL_A-U">
<name>GPL_A-U</name>
</ccc>
</cccs>
</ccc>
<ccc id ="1-J_J-I">
<name>J-I-Ang</name>           
<ccc id="1-J_J-I_GPL_A-I">
<name>GPL_A-I</name>
</ccc>
</ccc>
</cccs> 
</ccwc> 
<ccwc id="M">
<name>Ma</name>
<cccs>
<ccc id="M A-M">
<name>A-M</name>
</ccc>
</cccs>
</ccwc>
</ccs>

我不明白我应该在哪里打破分组并添加新节点。我使用的是XSLT 2.0版本。任何帮助都会非常感激。谢谢!

您可以使用像

这样的检查来实现顶级分组结构
<xsl:template match="/Rep/RepData">
<ccs>
<xsl:for-each-group select="Row" group-by="if (Field[@name = 'ID'][starts-with(., 'J')]) then 'J' else Field[@name = 'ID']">
<ccwc id="{current-grouping-key()}"></ccwc>
</xsl:for-each-group>
</ccs>
</xsl:template>

这给出了例如

<ccs>
<ccwc id="A"/>
<ccwc id="J"/>
<ccwc id="M"/>
</ccs>

我没有详细说明内部分组,但我想它仍然是你所拥有的;我也没有完全理解如何将输入J数据转换为1-J的规则,所以我没有试图实现它,它可能像做group-by="if (Field[@name = 'ID'][starts-with(., 'J')]) then '1-J' else Field[@name = 'ID']"一样容易。