I am a beginner to XSLT.
My Source XML is as below:
<Passengers>
<Passenger type="A" id="P1"/>
<Passenger type="A" id="P2"/>
<Passenger type="B" id="P3"/>
<Passenger type="C" id="P4"/>
</Passengers>
The out-put should be as below:
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
I have created XSLT as below
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" exclude-result-prefixes="xmlns">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:variable name="filter" select="'TK,AJ'"/>
<xsl:template match="Passengers">
<xsl:element name="Pax_Items">
<xsl:apply-templates select="Passenger"/>
</xsl:element>
</xsl:template>
<xsl:template match="Passenger">
<xsl:element name="Item">
<xsl:element name="Type">
<xsl:value-of select="@type"/>
</xsl:element>
<xsl:element name="Count">
<xsl:value-of select="count(//Passenger[@type=current()/@type])"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
With above XSLT i got the below output:
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
How can i omit or skip the duplicate element? Please help.
This is actually a good example of a grouping problem. In XSLT1.0, the most efficient way to do grouping is with a technique called "Muenchian Grouping", so it might be worthwhile learning about this.
In this case, you want to group Passenger elements by their @type attribute, so you would define a key to do this
<xsl:key name="Passengers" match="Passenger" use="@type"/>
Then, you need to select the Passenger elements which happen to be the first occurence of that element in the group for their @type attribute. This is done as follows:
<xsl:apply-templates
select="Passenger[generate-id() = generate-id(key('Passengers', @type)[1])]"/>
Note the use of generate-id which generates a unique ID for a node, allowing two nodes to be compared.
Then, to count the number of occurences in the group, it is straight-forward
<xsl:value-of select="count(key('Passengers', @type))"/>
Here is the full XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="Passengers" match="Passenger" use="@type"/>
<xsl:template match="Passengers">
<Pax_Items>
<xsl:apply-templates select="Passenger[generate-id() = generate-id(key('Passengers', @type)[1])]"/>
</Pax_Items>
</xsl:template>
<xsl:template match="Passenger">
<Item>
<Type>
<xsl:value-of select="@type"/>
</Type>
<Count>
<xsl:value-of select="count(key('Passengers', @type))"/>
</Count>
</Item>
</xsl:template>
</xsl:stylesheet>
When applied to your sample XML, the following is output
<Pax_Items>
<Item>
<Type>A</Type>
<Count>2</Count>
</Item>
<Item>
<Type>B</Type>
<Count>1</Count>
</Item>
<Item>
<Type>C</Type>
<Count>1</Count>
</Item>
</Pax_Items>
Also note there is no real reason to use xsl:element to output static elements. Just write out the element directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With