我需要转换这个XML输入:
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
<section id="a_2" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="x">
<attribute>
<name>John</name>
<origin>us</origin>
</attribute>
</user>
</section>
</node>
</root>
这是预期的输出:
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
<section id="a_2" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="x">
<attribute>
<name>John</name>
<origin>us</origin>
</attribute>
</user>
</section>
</node>
</root>
注意:重复意味着所有子/子具有相同的值,只要节点是同一个父节点(id和方法相同),节点就可以有1个或多个子节点,我们可以认为它总是在同一部分(id和方法是相同的)。
这可能吗?请赐教我
非常感谢。
欢呼声, 约翰
答案 0 :(得分:2)
<强>予。这个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="kElemWithAttribs" match="*[@id and @method]"
use="concat(generate-id(..), '+', name(), '+', @id, '+', @method)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[@id and @method
and
not(generate-id()
=
generate-id(key('kElemWithAttribs',
concat(generate-id(..),
'+',name(), '+', @id, '+', @method)
)[1]
)
)
]"/>
</xsl:stylesheet>
应用于提供的源XML文档时:
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
<section id="a_2" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
<section id="a_2" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="x">
<attribute>
<name>John</name>
<origin>us</origin>
</attribute>
</user>
</section>
</node>
</root>
会产生想要的正确结果:
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
<section id="a_2" method="run">
<item id="0" method="a">
<attribute>
<color>Red</color>
<status>1</status>
<condition>good</condition>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a" method="x">
<attribute>
<origin>us</origin>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="x">
<attribute>
<name>John</name>
<origin>us</origin>
</attribute>
</user>
</section>
</node>
</root>
解释:使用复合键正确使用 Muenchian method for grouping :
身份规则“按原样”复制每个节点。
xsl:key
定义将元素组与字符串键值相关联。如此定义的任何组都包含具有id
和method
属性的所有元素,并且(组中的所有)具有相同的父级,相同的名称,{{的相同字符串值1}}属性和id
属性的相同字符串值。
有一个模板会覆盖身份模板。它匹配具有method
和id
属性且不是其各自组中的第一个(按文档顺序排列)元素的任何元素。由于此模板没有正文,因此根本不会处理所有此类匹配元素,也不会将其复制到输出中(我们可以说它们已被“删除”)。
由于上面的3.,只有作为其组的第一个元素的元素才会与覆盖模板匹配。因此,这些元素由身份模板匹配并复制到输出 - 完全符合要求。
<强> II。 XSLT 2.0解决方案:
method
解释:正确使用 xsl:for-each-group
和<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@id]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by=
"concat(generate-id(..), '+', name(), '+', @id, '+', @method)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
属性。