如果我有这个 xml 文件:
<root>
<node id="a">
<Items id="a_1" method="pause">
<item id="0" method="pause">
<attribute>
<color>Red</color>
</attribute>
</item>
</Items>
<Items id="a_1" method="pause">
<item id="0" method="stop">
<attribute>
<color>Red</color>
</attribute>
</item>
</Items>
</node>
<node id="b">
<Persons id="b_1">
<person id="b_1b" method="pause">
<attribute>a</attribute>
</person>
<person id="b_1a" method="start">
<attribute>
<name>John</name>
</attribute>
</person>
<person id="b_1b" method="stop">
<attribute>a</attribute>
</person>
<person id="b_1a" method="pause">
<attribute>a</attribute>
</person>
</Persons>
<Persons id="b_1" method="start">
<person id="b_1a" method="stop">
<attribute>a</attribute>
</person>
<person id="b_1b" method="start">
<attribute>a</attribute>
</person>
<person id="b_1b" method="pause">
<attribute>a</attribute>
</person>
</Persons>
<Persons id="b_2">
<person id="b_1a" method="start">
<attribute>
<name>John</name>
</attribute>
</person>
</Persons>
</node>
</root>
预期的输出是:
<root>
<node id="a">
<Items id="a_1" method="pause">
</Items>
<Items id="a_1" method="pause">
<item id="0" method="stop">
<attribute>
<color>Red</color>
</attribute>
</item>
</Items>
</node>
<node id="b">
<Persons id="b_1">
</Persons>
<Persons id="b_1" method="start">
<person id="b_1a" method="stop">
<attribute>a</attribute>
</person>
<person id="b_1b" method="start">
<attribute>a</attribute>
</person>
<person id="b_1b" method="pause">
<attribute>a</attribute>
</person>
</Persons>
<Persons id="b_2">
<person id="b_1a" method="start">
<attribute>
<name>John</name>
</attribute>
</person>
</Persons>
</node>
</root>
该算法的关键在于停止方法。
- 如果它是最后一个删除所有节点并留下一个'停止
- 如果具有“停止”方法的节点不是最后一个,则删除具有“停止”的该节点及其之前的所有节点(在该停止之后保留所有节点)。
这必须发生在父母的id属性相同的孩子中,它只会删除子节点(删除用户节点后即使它是空的也离开父母)。
对于上面的例子:
- item id=0 pause 然后 item id=0 stop -> 结果将是item id=0 stop(父项:Items id=a_1-pause)。
- 人 id=b_1a 开始然后人 id=b_1a 暂停然后人 id=b1_a 停止(父母:人 id=b_1) - 所以结果变成只有人 id=b_1a 停止
- person id=b_1b pause 然后 person id=b_1b stop 然后 person id=b_1b start 然后 person id=b_1b pause -> 它将变成person id=b_1b start 然后 person id=b_1b pause(我们再次比较父 Person id 下的每个人=b_1; 在父级中,我们不关心其中一个是否没有方法,只要它与示例中所示的 id 相同)
这就是我只为“人”节点所拥有的。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Ignore person with 'stop' method which are not the last such person -->
<xsl:template match="person[@method='stop'][following::person[@method='stop']]"/>
<!-- Match other persons -->
<xsl:template match="person">
<!-- Copy the person if there isn't a following person with the same id and 'stop' method -->
<xsl:if test="not(following::person[@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>
是否可以更改以解决所有其他节点(节点和父名称可以是任何东西)?非常感谢。
亲切的问候,约翰