XSLT: the sum of a specific attribute value based on a different attribute name

I have the following xml document (provided by the other party)

<transactions> <transaction TaxAType="11" TaxAValue="111" TaxBType="2" TaxBValue="222" TaxCType="3" TaxCValue="333"/> <transaction TaxAType="11" TaxAValue="111" TaxBType="2" TaxBValue="222" TaxCType="3" TaxCValue="333"/> </transactions> 

I would like to write an XSLT document that converts these lines and sums up the value of Tax * if the corresponding Tax * Type = '11', for example.

Can this be done without using a template?

name (), substring (), etc. functions in XQuery? What do you think about it?

+4
source share
4 answers

Take a look at the following XSLT:

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" /> <xsl:template match="/"> Sum of TaxA where type = 11: <xsl:value-of select="sum(transactions/transaction[@TaxAType='11']/@TaxAValue)" /> Sum of all tax where type = 11: <xsl:value-of select="sum(transactions/transaction[@TaxAType='11']/@TaxAValue) + sum(transactions/transaction[@TaxBType='11']/@TaxBValue) + sum(transactions/transaction[@TaxCType='11']/@TaxCValue)" /> </xsl:template> </xsl:stylesheet> 

It calculates the amount of TaxAValue for nodes with TaxAType = 11 and the sum of the total tax value for nodes with Tax? Type = 11.

+13
source

Here is a somewhat detailed but general approach:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:param name="taxType" select="11" /> <xsl:template match="transactions"> <result> <xsl:variable name="allValues" select="transaction/@*[substring(local-name(), 5, 5) = 'Type'] [. = $taxType]" /> <xsl:call-template name="SumValues"> <xsl:with-param name="items" select="$allValues" /> </xsl:call-template> </result> </xsl:template> <xsl:template name="SumValues"> <xsl:param name="items" /> <xsl:param name="total" select="0" /> <xsl:choose> <xsl:when test="not($items)"> <xsl:value-of select="$total" /> </xsl:when> <xsl:otherwise> <xsl:variable name="currentItem" select="$items[1]" /> <xsl:variable name="currentValue"> <xsl:apply-templates select="$currentItem" mode="getMatchingValue" /> </xsl:variable> <xsl:call-template name="SumValues"> <xsl:with-param name="items" select="$items[position() > 1]" /> <xsl:with-param name="total" select="$total + $currentValue" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="@*" mode="getMatchingValue"> <xsl:variable name="typeCodeLetter" select="substring(local-name(), 4, 1)" /> <xsl:variable name="valueAttributeName" select="concat('Tax', $typeCodeLetter, 'Value')" /> <xsl:variable name="matchingValueAttribute" select="../@*[local-name() = $valueAttributeName]" /> <!-- Multiply by boolean to handle the case where the attribute wasn't found--> <xsl:value-of select="$matchingValueAttribute * boolean($matchingValueAttribute)"/> </xsl:template> </xsl:stylesheet> 

This should be able to handle any number of Tax*Type (as long as the * character is the only character), and the desired type can be passed as a parameter.

+1
source

This xml is not in a very suitable format to complete the type of processing you are requesting. your best option is to use javascript or some other language with XML capabilities (C #, Java, etc.) to extract the necessary details.

with javascript you can find any attribute with Tax * Type = 11 and then get the value of the next attribute

0
source

amount (transactions / transaction [@TaxAType = '11 '] / @ TaxAValue | @TaxBvalue | @TaxCvalue)

0
source

All Articles