YannickIngenierie
YannickIngenierie

Reputation: 622

How to remove a double appearing sibling node using XSLT

I've a xml file containing some product. It's a very big file. Then I make a xslt file to build another leighter xml file.

<file path="export/freexml.int/FR/26064804.xml" Product_ID="26064804" Updated="20150827060248" Quality="ICECAT" Supplier_id="11077" Prod_ID="30097568" Catid="2943" On_Market="0" Model_Name="Color Show 110 Urban Coral" Product_View="2819" HighPic="http://images.icecat.biz/img/norm/high/26064804-6070.jpg" HighPicSize="34989" HighPicWidth="400" HighPicHeight="355" Date_Added="20150127000000">
  <M_Prod_ID>0000030097568</M_Prod_ID>
  <M_Prod_ID>0000030097568</M_Prod_ID>
  <EAN_UPCS>
    <EAN_UPC Value="0000030097568" />
  </EAN_UPCS>
</file>

Here a sample where M_Prod are in double. And here my xslt, who catch some case where double appear, but I can't find for the hover case

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output  method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="ICECAT-interface">
        <xsl:apply-templates select="files.index"/>
    </xsl:template>

    <xsl:template match="files.index">
        <xsl:element name="files">
            <xsl:attribute name="Generated">
                <xsl:value-of select="@Generated"/>
            </xsl:attribute>
            <xsl:apply-templates select="file"/>
        </xsl:element>

    </xsl:template>

    <xsl:template match="file">
        <xsl:element name="file">
            <xsl:attribute name="path">
                <xsl:value-of select="@path"/>
            </xsl:attribute>
            <xsl:attribute name="Prod_ID">
                <xsl:value-of select="@Prod_ID"/>
            </xsl:attribute>
            <xsl:attribute name="Supplier_id">
                <xsl:value-of select="@Supplier_id"/>
            </xsl:attribute>
            <xsl:attribute name="Catid">
                <xsl:value-of select="@Catid"/>
            </xsl:attribute>
            <xsl:attribute name="Updated">
                <xsl:value-of select="@Updated"/>
            </xsl:attribute>
            <xsl:attribute name="Quality">
                <xsl:value-of select="@Quality"/>
            </xsl:attribute>
        </xsl:element>
        <xsl:apply-templates select="M_Prod_ID"/>
    </xsl:template>

    <xsl:template match="M_Prod_ID[not(. = ../@Prod_ID)]">
        <xsl:element name="file">
            <xsl:attribute name="path">
                <xsl:value-of select="../@path"/>
            </xsl:attribute>
            <xsl:attribute name="Prod_ID">
                <xsl:value-of select="."/>
            </xsl:attribute>
            <xsl:attribute name="Supplier_id">
                <xsl:choose>
                    <xsl:when test="@Supplier_id">
                        <xsl:value-of select="@Supplier_id"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="../@Supplier_id"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:attribute name="Catid">
                <xsl:value-of select="../@Catid"/>
            </xsl:attribute>
            <xsl:attribute name="Updated">
                <xsl:value-of select="../@Updated"/>
            </xsl:attribute>
            <xsl:attribute name="Quality">
                <xsl:value-of select="../@Quality"/>
            </xsl:attribute>
        </xsl:element>

    </xsl:template>

</xsl:stylesheet>

I see too grouping solution, But I can't finalyse correctly xslt file .

Update 1

Here my sample

Look there are 3 file nodes generated. I want only the two first node.

Update 2

I want

<files Generated="20150916022750">
   <file path="export/freexml.int/FR/26064804.xml"
         Prod_ID="30097568"
         Supplier_id="11077"
         Catid="2943"
         Updated="20150827060248"
         Quality="ICECAT"/>
   <file path="export/freexml.int/FR/26064804.xml"
         Prod_ID="0000030097568"
         Supplier_id="11077"
         Catid="2943"
         Updated="20150827060248"
         Quality="ICECAT"/></files>

Upvotes: 0

Views: 678

Answers (1)

Abel
Abel

Reputation: 57159

Question edited, following conclusions from discussion.

How to remove a double appearing sibling node using XSLT

There are several ways of doing that. First and foremost, you can use Muenchian grouping, but you have said that you find that too complex to grasp just yet. So let's look at an alternative.

One way is to add the following to your current stylesheet:

<xsl:template match="M_Prod_ID[. = preceding-sibling::M_Prod_ID[1]]" />

You may need to add a priority to the template, because if your other M_Prod_ID is to stay the way it is, they will have the same priority and then the latter will be chosen, or an error will be raised:

<xsl:template match="M_Prod_ID[. = preceding-sibling::M_Prod_ID[1]]" priority="10"/>

Test it

It is often a good idea to see something in action in a minimal context to understand how it works. So, I have taken your input file and ran it against the following simplified stylesheet. Please click here to see it in action on xsltransform.net.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() |@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="M_Prod_ID[. = preceding-sibling::M_Prod_ID[1]]" />

</xsl:stylesheet>

Which results in the following output (duplicate M_Prod_ID removed)

<file path="export/freexml.int/FR/26064804.xml" Product_ID="26064804" Updated="20150827060248" Quality="ICECAT" Supplier_id="11077" Prod_ID="30097568" Catid="2943" On_Market="0" Model_Name="Color Show 110 Urban Coral" Product_View="2819" HighPic="http://images.icecat.biz/img/norm/high/26064804-6070.jpg" HighPicSize="34989" HighPicWidth="400" HighPicHeight="355" Date_Added="20150127000000">
  <M_Prod_ID>0000030097568</M_Prod_ID>

  <EAN_UPCS>
    <EAN_UPC Value="0000030097568" />
  </EAN_UPCS>
</file>

Notes

You are using <xsl:attribute> <xsl:element> a lot, but you can also use literal result elements and attribute value templates:

<file path="{../@path}" Prod_ID="{.}" .....>
    <!-- any child elements go here -->

Upvotes: 1

Related Questions