我有这个 XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/> <xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="region/*/*/*
[deep-equal(.,preceding-sibling::*[name()=current()/name()]
[@id = current()/@id]
[../../@id = current()/../../@id][1])]" />
</xsl:stylesheet>
所以基本上任何后续的重复项(具有相同的名称、id、方法和子项)都将被删除,直到它被重置(被视为唯一的或第一次被发现)
如果具有相同和 id 的节点具有不同的方法,则会发生重置。
为了更清楚,我有这个简化的例子作为说明:
<elem id="1" method="a" />
<elem id="1" method="a" /> <!-- 1. this is duplicate -->
<elem id="1" method="b" /> <!-- 2. this elem id=1 has different method, so it will be the reset point for elem id=1 -->
<elem id="1" method="a" /> <!-- 3. this will be treated as unique because it's reset now so we don't remove this-->
<elem id="2" method="a" /> <!--4.-->
<elem id="1" method="a" /> <!-- this is repetitive for 3 and it willl be removed -->
<elem id="2" method="a" /> <!-- this is repetitive for 4 so we remove this-->
and will be removed -->
转换后将简化为:
<elem id="1" method="a" />
<elem id="1" method="b" />
<elem id="1" method="a" /> <!-- 3. this will be treated as unique because it's reset now so we don't remove this-->
<elem id="2" method="a" />
因此,如果它应用于我的 XML 输入:
<map>
<region>
<gridA id="1">
<blockA id="01" method="build">
<building1 id="x" method="build">
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be removed -->
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="01">
<building1 id="x" method="modify"> <!-- this will be the reset point -->
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be kept (prev node have same id but diff method so it's not considered as successive -->
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="02">
<building3 id="y" method="modify">
<otherchild>b</otherchild>
</building3>
<building2 id="x" method="demolish"/>
</blockA>
<blockA id="01">
<building1 id="y" method="build"> <!-- this one will be kept (diff id) -->
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be removed -->
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="02">
<building3 id="y" method="modify"> <!-- this one will be removed -->
<otherchild>b</otherchild>
</building3>
<building2 id="x" method="demolish"/> <!-- this one will be removed -->
</blockA>
</gridA>
<gridA id="2">
<blockA id="01" method="build">
<building1 id="x" method="build">
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be removed -->
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be kept (diff children) -->
<otherchild>b</otherchild>
</building1>
</blockA>
<blockA id="01">
<building1 id="x" method="build"> <!-- this one will be removed -->
<otherchild>b</otherchild>
</building1>
</blockA>
</gridA>
<gridB id="1">
...and so on..
</gridB>
</region>
</map>
这是预期的输出:
<map>
<region>
<gridA id="1">
<blockA id="01" method="build">
<building1 id="x" method="build">
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="01">
<building1 id="x" method="modify"> <!-- this will be the reset point -->
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be kept (prev node have same id but diff method) so it's not considered as successive -->
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="02">
<building3 id="y" method="modify">
<otherchild>b</otherchild>
</building3>
<building2 id="x" method="demolish"/>
</blockA>
<blockA id="01">
<building1 id="y" method="build"> <!-- this one will be kept (diff id) -->
<otherchild>a</otherchild>
</building1>
</blockA>
<blockA id="02"/>
</gridA>
<gridA id="2">
<blockA id="01" method="build">
<building1 id="x" method="build">
<otherchild>a</otherchild>
</building1>
<building1 id="x" method="build"> <!-- this one will be kept (diff children) -->
<otherchild>b</otherchild>
</building1>
</blockA>
<blockA id="01"/>
</gridA>
<gridB id="1">
...and so on..
</gridB>
</region>
</map>
此外,如果被比较的两个节点不共享相同的“gridA”级别节点,则不应将它们视为要删除的重复节点。
我也考虑使用
<xsl:value-of select="count($this-node/(preceding-sibling::* | ../preceding-sibling::*[@id = $this-node/parent::*/@id]/*)[name() = $this-node/name()][@id = $this-node/@id][deep-equal(*, $this-node/*)][@method = $this-node/@method]) mod 2 = 1"/>
作为我的重置算法,但第一个解决方案最好只需要调整它以在具有相同 ID 的兄弟姐妹上工作。(从示例中,它是<blockA id="xx">
:)或者如果有人有更好的解决方案,我真的很想知道。
我希望任何人都可以在这个问题上启发我,因为这对我来说很难理解。
非常感谢,并为冗长的问题道歉。