mmkd
mmkd

Reputation: 900

XSLT Exclude Specific Tags

I have a problem i am trying to resolve in an XSLT but i an unable to find a solution. The example below is related to a payment system it is adding items to a basket then removing them. The out XML provides a audit trail of actions conducted on a basket.

Senario:

Add Item (Id 1)

Add Item (Id 1) With a price change

Void Item (Id 1)

Void Item (Id 1) With a price change

Add Item (Id 1)

Add Item (Id 1)

Expected Outcome

Remove:

Add Item (Id 1)

Add Item (Id 1) With a price change

Output XML Contains

Void Item (Id 1)

Void Item (Id 1) With a price change

Add Item (Id 1)

Add Item (Id 1)

Input XML:

<xml>
    <product void="false">
        <sequence_number>1</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
    <product void="false">
        <sequence_number>2</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
        <price_change>
            <price>10</price>
        </price_change>
    </product>
    <product void="true">
        <sequence_number>3</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
        <price_change>
            <price>10</price>
        </price_change>
    </product>
    <product void="true">
        <sequence_number>4</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
    <product void="false">
        <sequence_number>5</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
    <product void="false">
        <sequence_number>6</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
</xml>

Expected outcome:

<xml>
    <product void="true">
        <sequence_number>3</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
        <price_change>
            <price>10</price>
        </price_change>
    </product>
    <product void="true">
        <sequence_number>4</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
    <product void="false">
        <sequence_number>5</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
    <product void="false">
        <sequence_number>6</sequence_number>
        <item_id>11111111</item_id>
        <price>12</price>
    </product>
</xml>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    
    <xsl:template match="//product[@void='false']">
        
        <xsl:if test="item_id != //product[@void='true']/item_id">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
        
    </xsl:template>
    
</xsl:stylesheet>

The problem with this is that it is deleting all products that are not voided and have the same id and not taking into account the number of void items vs the number of none void items.

If you have 1 void item it should only delete one product that is not voided but has exactly the same tags as itself

Upvotes: 2

Views: 952

Answers (1)

Matthew Green
Matthew Green

Reputation: 10401

Assuming your products always show up in sequence you can do a check against the preceding-sibling for true and then compare the item_id. Since your first two items don't have a void transaction preceding them it would not process those. So you can update your if statement to the below:

<xsl:if test="item_id = preceding-sibling::product[@void='true']/item_id">

That will then match your expected output.

Upvotes: 1

Related Questions