我需要删除在其包含一定的方法我的XML文件,并通过它出现例如这里为了一些节点是输入:如何使用XSLT或Xquery基于XML中的属性删除某个节点?
<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">
<user id="b_1b" method="pause">
<attribute>a</attribute>
</user>
<user id="b_1b" method="run">
<attribute>a</attribute>
</user>
<user id="b_1a" method="run">
<attribute>
<name>John</name>
</attribute>
</user>
<user id="b_1a" method="pause">
<attribute>a</attribute>
</user>
</section>
<section id="b_1" method="create">
<user id="b_1b" method="stop">
<attribute>a</attribute>
</user>
<user id="b_1a" method="stop">
<attribute>a</attribute>
</user>
<user id="b_1b" method="run">
<attribute>a</attribute>
</user>
<user id="b_1b" method="pause">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="run">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
如果我用这个方法:
<xsl:transform version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://localhost"
exclude-result-prefixes="my">
<!-- Copy everything by default -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match=" user[not(@method eq 'stop')][not(. is my:last(.))]
| user[ @method eq 'stop' ][not(. is my:last(.))]
| user[not(@method eq 'stop')][my:last(.)/@method eq 'stop']"/>
<!-- Get the last user for this section & user id -->
<xsl:function name="my:last">
<xsl:param name="user"/>
<xsl:sequence select="($user/../../section[@id eq $user/../@id]
/user [@id eq $user/@id]
)
[last()]"/>
</xsl:function>
</xsl:transform>
结果将是:
而期望的输出是:
<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">
</section>
<section id="b_1" method="create">
<user id="b_1a" method="stop">
<attribute>a</attribute>
</user>
**<user id="b_1b" method="run">
<attribute>a</attribute>
</user>**
<user id="b_1b" method="pause">
<attribute>a</attribute>
</user>
</section>
<section id="b_2">
<user id="b_1a" method="run">
<attribute>
<name>John</name>
</attribute>
</user>
</section>
</node>
</root>
所以这就是命令的工作原理。如果最后发生“停止”,则其他具有相同用户标识的方法的其他节点(例如暂停和运行)将被删除。 但是,如果它不是那么'停止'本身的节点和之前的所有节点'停止'将被删除。
这必须发生在相同的部分ID,它将只删除用户节点(即使在删除用户节点后它是空的,仍保留部分ID)。 希望这个解释不会令人困惑。
是否有可能通过仅使用XSLT来完成?还是必须使用xQuery遍历每个节点? 有人可以启发我吗? 非常感谢。
约翰
我认为你重复的是一个错字,因为XML ID应该是唯一的(如果它确实是一个ID属性)。 –
2012-04-17 17:32:07
你可以用XSLT(或者我认为的XQuery)来完成,不需要同时使用两者。 – LarsH 2012-04-17 17:44:16
请澄清“if'stop'最后发生的含义。起初,我以为你的意思是当与方法=“停止”作为最后一个孩子发生。但既然这不符合你给的例子,我猜不是。 –
2012-04-17 18:19:58