Reputation: 900
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.
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)
Remove:
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)
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
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