|
Subject: Re: [xsl] How to do this tricky elimination on XML using XSLT 2.0? From: Jo Na <jkoe888@xxxxxxxxx> Date: Tue, 19 Jun 2012 21:57:42 +0700 |
Dear Dr. Kay,
Thank your for your guide.
I modified the solution into:
<xsl:variable name="removed-nodes" as="element(*)*">
<xsl:for-each-group select="//blockA/*" group-by="concat(@id,
'~', @method, '~', otherchild)">
<xsl:sequence select="subsequence(current-group(), 2)"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:template match="@* | node()">
<xsl:if test="empty(. intersect $removed-nodes)">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
It's almost correct just need to address two things:
1. Everytime a successive node with the `same id` has `different method`,
the `boundary` for the next removal for that `id` is reset.
2. The removal cannot combine two different ancestor (<gridA id="1">
and <gridA id="2">)
**for example:**
<elem id="1" method="a" />
<elem id="1" method="a" /> <!-- this is repetitive for elem id=1
and will be removed -->
<elem id="1" method="b" />
<elem id="1" method="a" /> <!-- this is the new boundary for
removal elem id=1 and will not be removed -->
<elem id="2" method="a" />
<elem id="1" method="a" /> <!-- this is repetitive for elem id=1
and will be removed -->
<elem id="2" method="a" /> <!-- this is repetitive for elem id=2
and will be removed -->
**will be simplified into:**
<elem id="1" method="a" />
<elem id="1" method="b" />
<elem id="1" method="a" /> <!-- this is the new boundary for
removal elem id=1 and will not be removed -->
<elem id="2" method="a" />
Please let me know how I can achieve such things. Thanks very much once
again.
On Tue, Jun 19, 2012 at 9:20 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> I think I would tackle this in two passes. First use xsl:for-each-group to
> identify the nodes to be removed; then do a modified identity transform
that
> retains only the nodes not in this list.
>
> The first pass is something like this:
>
> <!-- **Two node that have the same `name` and `id` will be considered
> *repetitive* if it appears one after another and it has the same `method`
> and `children`.** -->
> <xsl:variable name="removed-nodes" as="element(*)*">
> <xsl:for-each-group select="//blockA/*" group-by="concat(@id, '~', @method,
> '~', otherchild)">
> <xsl:sequence select="subsequence(current-group(), 2)"/>
> </xsl:for-each-group>
> </xsl:variable>
>
> The second pass is:
>
> <xsl:template match="*">
> <xsl:if test="empty(. intersect $removed-nodes)">
> <xsl:copy>
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates/>
> </xsl:copy>
> </xsl:if>
> </xsl:template>
>
> Michael Kay
> Saxonica
>
>
> On 19/06/2012 10:14, Jo Na wrote:
>>
>> Hi,
>> I have this input 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">
>> <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>
>>
>> Expected Output:
>>
>> <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">
>> <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>
>> The XSLT so far:
>>
>> <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::*[name()=current()/name()]
>> [@id = current()/@id]
>> [../../@id = current()/../../@id][1])]" />
>> </xsl:stylesheet>
>>
>> the problem with the XSLT right now is that it cannot differentiate
>> duplicates that happens in siblings (i.e blockA with the same id).
>>
>> I need to remove a node that are considered as *repetitive*.
>>
>> **Two node that have the same `name` and `id` will be considered
>> *repetitive* if it appears one after another and it has the same
>> `method` and `children`.**
>>
>> **for example:**
>>
>> <elem id="1" method="a" />
>> <elem id="1" method="a" /> <!-- this is repetitive for id=1-->
>> <elem id="1" method="b" />
>> <elem id="1" method="a" /> <!-- this is the new boundary for removal
>> id=1-->
>> <elem id="2" method="a" />
>> <elem id="1" method="a" /> <!-- this is repetitive for id=1 -->
>> <elem id="2" method="a" /> <!-- this is repetitive for id=2 -->
>>
>> **will be simplified into:**
>>
>> <elem id="1" method="a" />
>> <elem id="1" method="b" />
>> <elem id="1" method="a" /> <!-- this is the new boundary for removal
>> id=1-->
>> <elem id="2" method="a" />
>>
>> **- Everytime a successive node with the `same id` has `different
>> method`,
>> the `boundary` for the next removal for that `id` is reset.**
>>
>> - we need to take into account duplicates that are under one parent
>> or siblings (two or more parents nodes that has the same element name
>> and id) i.e (in example: `blockX`)
>> - if the two nodes being compared did not share the same `gridX`
>> level, then they should not be considered as duplicates to be removed
>>
>> Please let me know how to achieve such transformation using XSLT 2.0.
>> Thanks very much for the help.
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] How to do this tricky eli, Michael Kay | Thread | [xsl] How to categorize elements ha, Amit Agarwal |
| RE: [xsl] How to do this unique gro, Scott Trenda | Date | Re: [xsl] Call java function to do , Ming Yu |
| Month |