我需要在我的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="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>
而预期输出为:
<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>
所以这就是订单的运作方式。如果"stop"最后发生,那么具有相同用户 ID 的其他方法(例如暂停和运行)的任何其他节点都将被删除。但如果不是,那么带有"stop"本身的节点和"stop"之前的所有节点将被移除。
这必须发生在同一个节 id 中,并且它将只删除用户节点(即使删除用户节点后段 ID 为空,也要保留该段 ID)。希望解释不会令人困惑。
非常感谢。
干杯John
试试这个 XSLT,它减少了条件的数量,并且也可以在 XSLT 1.0 中工作
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Ignore users with 'stop' method which are not the last such user -->
<xsl:template match="user[@method='stop'][following::user[@method='stop']]"/>
<!-- Match other users -->
<xsl:template match="user">
<!-- Copy the user if there isn't a following user with the same id and 'stop' method -->
<xsl:if test="not(following::user[@id=current()/@id][@method='stop'])">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这也应该生成预期的输出
我已经找到了答案
<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')][following::user[@method eq 'stop']]
| user[(@method eq 'stop')][not(. is my:last(.))]
| user[not(@method eq 'stop')][my:last(.)/@method eq 'stop']"/>
<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>
请评论这是否是解决它的正确方法,或者任何人有更好的解决方案。