使用xslt删除xml中基于多个属性的重复节点
我有一个需要用xslt转换的输入XML使用xslt删除xml中基于多个属性的重复节点,xml,xslt,Xml,Xslt,我有一个需要用xslt转换的输入XML <root> <node id="a"> <section id="a_1" method="run"> <item id="0"> <attribute> <color>Red</color> </attribute
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
红色
红色
红色
约翰
A.
A.
约翰
预期产出:
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
红色
红色
约翰
A.
约翰
消除哪个节点无关紧要,只要它具有相同的元素名称、id和方法,其中一个节点就会被删除。
知道xsl是什么样子的吗
注意:元素名可以是任何不必是的东西,并且在整个文件中有多个元素名;只要它具有相同的元素名称、id和属性(例如,method=create),其中一个将被删除
非常感谢。
干杯
JohnXSL文件:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="node">
<node>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</node>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][1]">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id != 'b_1']">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][position() > 1]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<?xml version='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:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[not(@id eq preceding::*[local-name() eq local-name(.)]/@id)]">
<xsl:element name="{name()}">
<xsl:copy-of select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
转变:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="node">
<node>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</node>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][1]">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id != 'b_1']">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][position() > 1]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<?xml version='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:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[not(@id eq preceding::*[local-name() eq local-name(.)]/@id)]">
<xsl:element name="{name()}">
<xsl:copy-of select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
红色
红色
约翰
A.
约翰
希望这有帮助 [编辑] 在同一输入文件上尝试此XSL:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="node">
<node>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</node>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][1]">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id != 'b_1']">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][position() > 1]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<?xml version='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:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[not(@id eq preceding::*[local-name() eq local-name(.)]/@id)]">
<xsl:element name="{name()}">
<xsl:copy-of select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
结果是:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="node">
<node>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</node>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][1]">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id != 'b_1']">
<section>
<xsl:copy-of select="node()|@*"/>
</section>
</xsl:template>
<xsl:template match="section[@id = 'b_1'][position() > 1]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<?xml version='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:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[not(@id eq preceding::*[local-name() eq local-name(.)]/@id)]">
<xsl:element name="{name()}">
<xsl:copy-of select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
红色
红色
约翰
A.
A.
约翰
[/EDIT]I.这里是一个简短而高效(使用键)的XSLT1.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(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(name(), '+', @id, '+', @method)
)[1]
)
)
]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
在提供的XML文档上应用此转换时:
<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(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(name(), '+', @id, '+', @method)
)[1]
)
)
]"/>
</xsl:stylesheet>
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1c">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
<root>
<node id="a">
<section id="a_1" method="run">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
<section id="a_2">
<item id="0">
<attribute>
<color>Red</color>
</attribute>
</item>
</section>
</node>
<node id="b">
<section id="b_1" method="create">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1b">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
使用复合键。在这里,我们忽略(删除)不是组中第一个的每个节点
II。XSLT 2.0解决方案--甚至更短、效率更高:
<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="node">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*"
group-by="concat(name(), '+', @id, '+', @method)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
说明:
<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="node">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*"
group-by="concat(name(), '+', @id, '+', @method)">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
正确使用带有group by
属性的。感谢您的回答,但正如我在问题中提到的,我们只需要同时删除1个重复节点。因此,在这种情况下,我们仍然需要保留和相应的孩子。你介意更新解决方案吗?非常感谢。谢谢@Cylian!非常感谢。还有一件事是可以概括的,我的意思是它可以是任何元素,只要元素名称、id和属性(method=create)相同,其中一个将被删除您使用的是哪个XSLT版本?看到这一点,没有属性的情况就不同了还有一件事。。如果只有在同一父项下(节id)才能删除重复项,则如何修复此代码。谢谢。@John:请你提出一个新的问题——带一个源XML文档和一个想要的结果,并解释一下新的要求,好吗?然后通知我,我很乐意回答。我会在几分钟后发布并通知你。谢谢你的时间。如果问题很复杂,我向你道歉。我真的不知道。再次感谢。