How to make this XSL transformation consider only for siblings with the same id?

dwaynehornet

New Member
I have this XSLT 2.0:\[code\]<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>\[/code\]So basically any subsequent duplicate (with same name, id, method and children) will be removed until it is reset (treated as unique or the first time it's found)The reset will happen if node with the same and id has different method. To make it clearer I have this simplified example as illustration:\[code\]<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 -->\[/code\]After transformation it will be simplified into:\[code\] <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" />\[/code\]So if it is applied to my XML input:\[code\]<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>\[/code\]Here is the expected output:\[code\]<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>\[/code\]Also if the two nodes being compared did not share the same 'gridA' level node, then they should not be considered as duplicates to be removed.I've also considering to use \[code\]<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"/>\[/code\]as my resetting algorithm, but the first solution is better just need to tweak it to work on the siblings with same id. (from the example, it is: \[code\]<blockA id="xx">\[/code\]) or if anyone has better solutions I would really like to know.I hope anyone can enlighten me on this problem as this is very difficult for me to understand.Thanks very much and apologize for the long questions.
 
Back
Top