如果我有这个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属性相同的孩子中发生,并且只删除子节点(即使删除了用户节点后父母也是空的)。< / p>
对于上面的示例: 这就是我只为'人'节点所拥有的。 是否可以更改为解决所有其他节点(节点和父名称可以是任何东西)?
非常感谢。
<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>
答案 0 :(得分:0)
这必须发生在同一个父母身上
我猜这意味着你之前提到的约束只适用于兄弟节点。但是你的id =“0”的例子表明这不是真的。所以我想我不明白上面的条款。
更新:这并不意味着“在一个父元素的子元素中”,而是“在父元素属性具有相同值的元素中”。
到目前为止我对规范的理解:
如果最后出现一个带'stop'方法的元素,那么将删除具有相同用户ID的其他方法(例如'pause'和'run')的任何其他节点。但是如果一个带有'stop'方法的元素不是最后一个,那么带有'stop'的元素和那个'stop'之前的所有元素(具有相同的id?)将会被删除。
在我看来,这可以概括为:
如果有一个带有'stop'方法的元素,那么该元素以及具有相同元素名称和相同id属性的任何前面的元素将被删除。
如果此摘要不正确,请澄清。
是否可以更改为解决所有其他节点(节点和父名称) 可以是任何东西)?
我还没有想过只能通过模板匹配来实现这一目标的方法。但它可以像你一样在xsl:if:
中完成<xsl:template match="*">
<!-- Copy the element if there isn't a following sibling element with
the same name, same id and 'stop' method, and if the element itself
doesn't have a 'stop' method. -->
<xsl:if test="not(@method = 'stop' or
following::*[local-name() = local-name(current()) and
@id = current()/@id and
../@id = current()/../@id and
@method = 'stop'])">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
我有点难以理解您对算法的规范,因此如果上述方法无法产生预期结果,请举一个具体示例,说明其结果与预期结果的不同之处,并阐明规范。
更新:我已根据最近的评论稍微更新了上述代码,但现在还没有完全符合我现在所理解的规范。今晚我会努力研究它。 (其他人也欢迎拍摄!)