我假设您的输入 XML 有一个root
节点,该节点将所有内容包装起来以制作格式良好的文档。我还假设所有allocelement
的拼写都是正确的(你有一些拼写为 as alloclement
)。我还假设您要删除由标签名称及其文本值标识的重复项。
使用XSLT 1.0:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="code" match="allocelement/code" use="."/>
<xsl:key name="code-sibling"
match="allocelement/*[name() != 'code']"
use="concat(parent::*/code, '|', name(), '|', .)"/>
<xsl:template match="@* | node()" name="copy">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="root/allocelement[1]"/>
</xsl:template>
<xsl:template match="allocelement">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates
select="(. | following-sibling::allocelement)/code
[generate-id() = generate-id(key('code', .)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="code">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="."/>
<xsl:apply-templates
select="key('code', .)/(preceding-sibling::* | following-sibling::*)
[generate-id() =
generate-id(key('code-sibling', concat(parent::*/code, '|', name(), '|', .))[1])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于:
<root>
<allocelement>
<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>1</alc>
<amount>4587</amount>
<code>1111</code>
</allocelement>
<allocelement>
<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>2</alc>
<amount>80000</amount>
<code>1111</code>
</allocelement>
<allocelement>
<hd1>875</hd1>
<hd2>455</hd2>
<hd3>455</hd3>
<alc>2</alc>
<amount>80000</amount>
<code>1112</code>
</allocelement>
</root>
产生:
<root>
<allocelement>
<code>1111<hd1>12</hd1>
<hd2>14</hd2>
<hd3>87</hd3>
<alc>1</alc>
<amount>4587</amount>
<alc>2</alc>
<amount>80000</amount>
</code>
<code>1112<hd1>875</hd1>
<hd2>455</hd2>
<hd3>455</hd3>
<alc>2</alc>
<amount>80000</amount>
</code>
</allocelement>
</root>
这是它的工作原理。默认路由是身份转换。我们首先中断allocelement
并将转换发送到不同的路线。我们让它复制唯一code
元素(由元素的文本值标识的唯一性)及其值,然后在code
共享相同值的所有节点的所有前/后兄弟姐妹上应用模板。这些现在将是节点的子节点code
。然后我们为那些唯一的兄弟姐妹(属于code
相同的值,具有相同的名称和相同的文本值)调用身份转换。
一注。混合内容从来都不是一个好主意。看看你是否真的需要在code
.
使用XSLT 2.0,您可以远离generate-id()
s:
<xsl:template match="allocelement">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="(. | following-sibling::allocelement)/code" group-by=".">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="code">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="."/>
<xsl:for-each-group select="key('code', .)/(preceding-sibling::* | following-sibling::*)"
group-by="concat(parent::*/code, '|', name(), '|', .)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>