Loop over nodes with if condition and create new node - xslt

I would like to create a new node based on if condition, but I got stuck:
Input:
<SHOP>
<ITEM>
<name>Apple</name>
<TP>
<name>Color</name>
<size>red</size>
</TP>
<TP>
<name>Code</name>
<size>14</size>
</TP>
</ITEM>
<ITEM>
<name>Bananas</name>
<TP>
<name>Color</name>
<size>yellow</size>
</TP>
<TP>
<name>Code</name>
<size>16</size>
</TP>
</ITEM>
</SHOP>
I am trying to use this XSLT:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="SHOP/ITEM/TP">
<PARAM>
<xsl:if test="name = 'Color'">
<span class="color"><xsl:value-of select="./size"/></span>
</xsl:if>
<xsl:if test="name = 'Code'">
<span class="code"><xsl:value-of select="./size"/></span>
</xsl:if>
</PARAM>
</xsl:template>
</xsl:stylesheet>
The only problem is, that the output is a multiple <PARAM> node, while I want one.
<?xml version="1.0" encoding="UTF-8"?>
<SHOP>
<ITEM>
<name>Apple</name>
<PARAM>
<span class="color">red</span>
</PARAM>
<PARAM>
<span class="code">14</span>
</PARAM>
</ITEM>
<ITEM>
<name>Bananas</name>
<PARAM>
<span class="color">yellow</span>
</PARAM>
<PARAM>
<span class="code">16</span>
</PARAM>
</ITEM>
</SHOP>
Desidered output:
<?xml version="1.0" encoding="UTF-8"?>
<SHOP>
<ITEM>
<name>Apple</name>
<PARAM>
<span class="color">red</span>
<span class="code">14</span>
</PARAM>
</ITEM>
<ITEM>
<name>Bananas</name>
<PARAM>
<span class="color">yellow</span>
<span class="code">16</span>
</PARAM>
</ITEM>
</SHOP>

How about:
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="ITEM">
<xsl:copy>
<xsl:apply-templates select="* except TP" />
<PARAM>
<xsl:apply-templates select="TP" />
</PARAM>
</xsl:copy>
</xsl:template>
<xsl:template match="TP">
<span class="{lower-case(name)}">
<xsl:value-of select="size"/>
</span>
</xsl:template>
</xsl:stylesheet>

Related

Build nodes from xpath

I have a source xml and from this source xml I like to select the nodes given by a path e.g. /shiporder/item/title and /shiporder/shipto/name from the sample source:
<?xml version="1.0" encoding="utf-16"?>
<shiporder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orderid="orderid1">
<orderperson>orderperson1</orderperson>
<shipto>
<name>name1</name>
</shipto>
<item>
<title>foo</title>
</item>
<item>
<title>bar</title>
</item>
</shiporder>
And I like to transform those nodes to certain target tree e.g. each /shiporder/item/title from the source xml should copied to root/Customer/Name/Title in the target xml tree. So my idea was to generate for each level in the source path a template and call this template from the preceding level:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:func="http://www.functx.com">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="/shiporder"/>
</root>
</xsl:template>
<xsl:template match="/shiporder">
<Customer>
<xsl:apply-templates select="item"/>
<xsl:apply-templates select="shipto"/>
</Customer>
</xsl:template>
<xsl:template match="/shiporder/item">
<Name>
<xsl:apply-templates select="title"/>
</Name>
</xsl:template>
<xsl:template match="/shiporder/shipto">
<Address>
<xsl:apply-templates select="name"/>
</Address>
</xsl:template>
<xsl:template match="/shiporder/item/title">
<Title>
<xsl:value-of select="text()" />
</Title>
</xsl:template>
<xsl:template match="/shiporder/shipto/name">
<Street>
<xsl:value-of select="text()" />
</Street>
</xsl:template>
</xsl:stylesheet>
There for I get a huge stylesheet if I have a huge list of source-paths. Has some one a more feasible idea to reach the target?

how to modify one xml input using variable from second xml input in XSLT?

My question is how to change values in <color> in sample1.xml based on the same <id> in sample2.xml
sample1.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<id>1</id>
<color>red</color>
</item>
<item>
<id>2</id>
<color>blue</color>
</item>
<item>
<id>3</id>
<color>green></color>
</item>
</root>
sample 2.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<id>1</id>
<color>yellow</color>
</item>
<item>
<id>3</id>
<color>white</color>
</item>
</root>
expected output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<id>1</id>
<color>yellow</color>
</item>
<item>
<id>2</id>
<color>blue</color>
</item>
<item>
<id>3</id>
<color>white></color>
</item>
</root>
I only know how to copy entire sample1.xml to output, but I don't know how to remember ids from sample2.xml, and by that values make changes to sample1.
Don't know if is possible, but probably I must use variables on some unknown way.
Here is my code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon"
version="2.0">
<xsl:output method="xml" indent="yes" media-type="text/xml" />
<xsl:param name="sample1"/>
<xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>
<xsl:param name="sample2"/>
<xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>
<xsl:template match="/" name="initial">
<xsl:apply-templates select="$sample1_xml/node()"/> <!-- this is only for copying entire sample1 file -->
</xsl:template>
<!-- copy all nodes and values -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I really don't have idea what is the right way to do that, because I am new to XSLT 2.0. Any help will be much appreciated.
I was beaten to this by Martin Honnen, but here's my solution:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon"
version="2.0">
<xsl:output method="xml" indent="yes" media-type="text/xml"/>
<xsl:param name="sample1"/>
<xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>
<xsl:param name="sample2"/>
<xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>
<xsl:template match="/" name="initial">
<xsl:apply-templates select="$sample1_xml/node()"/>
<!-- this is only for copying entire sample1 file -->
</xsl:template>
<!-- copy all nodes and values -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/item/color">
<xsl:param name="id" select="parent::item/id/text()"/>
<xsl:copy>
<xsl:choose>
<xsl:when test="$sample2_xml/root/item[id=$id]/color">
<xsl:value-of select="$sample2_xml/root/item[id=$id]/color/text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
Define a key <xsl:key name="id" match="item" use="id"/> and then add a template
<xsl:template match="item[key('id', id, $sample2_xml)]/color">
<xsl:copy-of select="key('id', ../id, $sample2_xml)/color"/>
</xsl:template>
So the complete sample is
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs saxon"
xmlns:saxon="http://saxon.sf.net/"
version="2.0">
<xsl:output method="xml" indent="yes" media-type="text/xml" />
<xsl:param name="sample1" as="xs:string"><![CDATA[<root>
<item>
<id>1</id>
<color>red</color>
</item>
<item>
<id>2</id>
<color>blue</color>
</item>
<item>
<id>3</id>
<color>green></color>
</item>
</root>]]></xsl:param>
<xsl:param name="sample1_xml" select="saxon:parse($sample1)"/>
<xsl:param name="sample2" as="xs:string"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<id>1</id>
<color>yellow</color>
</item>
<item>
<id>3</id>
<color>white</color>
</item>
</root>]]></xsl:param>
<xsl:param name="sample2_xml" select="saxon:parse($sample2)"/>
<xsl:key name="id" match="item" use="id"/>
<xsl:template match="/" name="initial">
<xsl:apply-templates select="$sample1_xml/node()"/> <!-- this is only for copying entire sample1 file -->
</xsl:template>
<!-- copy all nodes and values -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[key('id', id, $sample2_xml)]/color">
<xsl:copy-of select="key('id', ../id, $sample2_xml)/color"/>
</xsl:template>
</xsl:stylesheet>

how to check and replace the null date using xslt

I want to check if my expiry date is null than i want to take the value from CreationDate.
My XML is like
<CreationDate>2017-03-18</CreationDate> <ExpiresDate>20170318</ExpiresDate>
and in my xsl
<xsl:element name="NewDeliveryDueDate">
<xsl:call-template name="FormatDate">
<xsl:with-param name="DateTime" select="Product/ExpiresDate"/>
</xsl:call-template>
</xsl:element>
&comma;
Please suggest.
Your question is incomplete. Perhaps this could work for you:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ExpiresDate[not(string())]">
<xsl:copy>
<xsl:value-of select="translate(../CreationDate, '-', '')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this is applied to the following example input:
<root>
<item>
<CreationDate>2017-03-18</CreationDate>
<ExpiresDate>20170318</ExpiresDate>
</item>
<item>
<CreationDate>2017-03-09</CreationDate>
<ExpiresDate/>
</item>
</root>
the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<CreationDate>2017-03-18</CreationDate>
<ExpiresDate>20170318</ExpiresDate>
</item>
<item>
<CreationDate>2017-03-09</CreationDate>
<ExpiresDate>20170309</ExpiresDate>
</item>
</root>

increment counter in XSLT 1.0

This is the input XML:
<Move-Afile>
<Afile>
<Item>
<PackNumber>1234</PackNumber>
</Item>
<Item>
<PackNumber>567</PackNumber>
</Item>
<Item>
<PackNumber>567</PackNumber>
</Item>
<Item>
<PackNumber>126</PackNumber>
</Item>
<Item>
<PackNumber>876</PackNumber>
</Item>
</Afile>
</Move-Afile>
<Item> is an unbounded element which contains <PackNumber> as a child element. For each pack number we need to increment the counter variable, but here one condition is present like if previous <PackNumber> is equal to current <PackNumber> we have to ignore the counter (there is no need to increment) like below output.
Inside the for-each, can we get the counter like below XSLT sample?
This is my XSLT template
<xsl:template match="/">
<A>
<target>
<xsl:for-each select="/inp1:Move-Afile/inp1:Afile/inp1:Item/inp1:PalletNumber">
<xsl:variable name="count">
<!-- get the count here-->
</xsl:variable>
<counter>$count</counter>
<PNumber><xsl:value-of select="."/></PNumber>
</xsl:for-each>
</target>
</A>
</xsl:template>
This is the XML output:
<A>
<target>
<Item>
<counter>1</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>1234</PNumber>
</Item>
<Item>
<counter>2</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>567</PNumber>
</Item>
<Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the count-->no need to increment
<PNumber>567</PNumber>
</Item>
<Item>
<counter>3</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count-->
<PNumber>126</PNumber>
</Item>
<Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the count-->no need to increment
<PNumber>126</PNumber>
</Item>
</target>
</A>
XML output 2:
<?xml version="1.0"?>
<A>
<target>
<counter>1</counter>
<PNumber>1234</PNumber>
<counter>2</counter>
<PNumber>567</PNumber>
<!-- IF PNumber is equal we have to ignore the Total loop -->
<counter>3</counter>
<PNumber>126</PNumber>
<counter>4</counter>
<PNumber>876</PNumber>
</target>
</A>
Try this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" />
<xsl:template match="PackNumber">
<xsl:if test="not(preceding::PackNumber =.)" >
<!-- if previous <PackNumber> is not equal to current <PackNumber> t-->
<counter>
<xsl:value-of select="count(preceding::PackNumber[not(preceding::PackNumber= .)])+1"/>
</counter>
</xsl:if>
<PNumber>
<xsl:value-of select="."/>
</PNumber>
</xsl:template>
<xsl:template match="/">
<A>
<target>
<xsl:apply-templates select="//Item"/>
</target>
</A>
</xsl:template>
</xsl:stylesheet>
Update according the changed question:
get the count here (inside a for each loop as variable)
Try this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" />
<xsl:template match="PackNumber" mode="count">
<xsl:value-of select="count(preceding::PackNumber
[not(preceding::PackNumber= .)and not( . = current()/. ) ])+1"/>
</xsl:template>
<xsl:template match="/">
<A>
<target>
<xsl:for-each select="//Item/PackNumber">
<xsl:variable name="count">
<xsl:apply-templates select="." mode="count"/>
</xsl:variable>
<counter>
<xsl:value-of select="$count"/>
</counter>
<PNumber>
<xsl:value-of select="."/>
</PNumber>
</xsl:for-each>
</target>
</A>
</xsl:template>
</xsl:stylesheet>
Update Output:
<?xml version="1.0"?>
<A>
<target>
<counter>1</counter>
<PNumber>1234</PNumber>
<counter>2</counter>
<PNumber>567</PNumber>
<counter>2</counter>
<PNumber>567</PNumber>
<counter>3</counter>
<PNumber>126</PNumber>
<counter>4</counter>
<PNumber>876</PNumber>
</target>
</A>
Here is a short and very efficient solution, using Muenchian grouping:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kPackNByVal" match="PackNumber" use="."/>
<xsl:template match="Afile">
<A>
<target>
<xsl:apply-templates select=
"*/*[generate-id() = generate-id(key('kPackNByVal',.)[1])]"/>
</target>
</A>
</xsl:template>
<xsl:template match="PackNumber">
<counter><xsl:value-of select="position()"/></counter>
<PNumber><xsl:value-of select="."/></PNumber>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<Move-Afile>
<Afile>
<Item>
<PackNumber>1234</PackNumber>
</Item>
<Item>
<PackNumber>567</PackNumber>
</Item>
<Item>
<PackNumber>567</PackNumber>
</Item>
<Item>
<PackNumber>126</PackNumber>
</Item>
<Item>
<PackNumber>876</PackNumber>
</Item>
</Afile>
</Move-Afile>
the wanted, correct result is produced:
<A>
<target>
<counter>1</counter>
<PNumber>1234</PNumber>
<counter>2</counter>
<PNumber>567</PNumber>
<counter>3</counter>
<PNumber>126</PNumber>
<counter>4</counter>
<PNumber>876</PNumber>
</target>
</A>
If the result you need is what you show in your second XML sample, then this stylesheet is all you need.
All it does is copy the PackNumber from only those Item elements that have no previous matching PackNumber.
The count is calculated as one more than the number of preceding Item elements that have no matching predecessor.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="/">
<A>
<target>
<xsl:apply-templates select="*"/>
</target>
</A>
</xsl:template>
<xsl:template match="Item">
<xsl:if test="not(PackNumber = preceding-sibling::Item/PackNumber)">
<counter>
<xsl:value-of select="1+count(preceding-sibling::Item[not(PackNumber = preceding-sibling::Item/PackNumber)])"/>
</counter>
<xsl:copy-of select="PackNumber"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
output
<A>
<target>
<counter>1</counter>
<PackNumber>1234</PackNumber>
<counter>2</counter>
<PackNumber>567</PackNumber>
<counter>3</counter>
<PackNumber>126</PackNumber>
<counter>4</counter>
<PackNumber>876</PackNumber>
</target>
</A>
Rather than using counter variable and attempting to increment its value every time (Which anyway not going to happen as the variables in xsl are actually constants), try using position(), which can work as a unique incrementing identifier. Following is an example of the syntax using position():
<xsl:variable name="counterAlias" select="position()"/>

Doing a pivot using XSLT

I have an xml file like this:
<root>
<item>
<name>one</name>
<status>good</status>
</item>
<item>
<name>two</name>
<status>good</status>
</item>
<item>
<name>three</name>
<status>bad</status>
</item>
<item>
<name>four</name>
<status>ugly</status>
</item>
<item>
<name>five</name>
<status>bad</status>
</item>
</root>
I want to transform this using XSLT to get something like:
<root>
<items><status>good</status>
<name>one</name>
<name>two</name>
</items>
<items><status>bad</status>
<name>three</name>
<name>five</name>
</items>
<items><status>ugly</status>
<name>four</name>
</items>
</root>
In other words, I get a list of items, each with a status, and I want to turn it into a list of statuses, each with a list of items.
My initial thought was to do apply-templates matching each status type in turn, but that means I have to know the complete list of statuses. Is there a better way to do it?
Thanks for any help.
Muench to the rescue!
<?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" indent="yes" encoding="UTF-8"/>
<xsl:key name="muench" match="/root/item/status" use="."/>
<xsl:template match="/">
<root>
<xsl:for-each select="/root/item/status[generate-id() = generate-id(key('muench',.)[1])]">
<xsl:call-template name="pivot">
<xsl:with-param name="status" select="."/>
</xsl:call-template>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template name="pivot">
<xsl:param name="status"/>
<items>
<status><xsl:value-of select="$status"/></status>
<xsl:for-each select="/root/item[status=$status]">
<name><xsl:value-of select="name"/></name>
</xsl:for-each>
</items>
</xsl:template>
</xsl:stylesheet>
Yes, this can be done in XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- -->
<xsl:key name="kStatByVal"
match="status" use="."/>
<!-- -->
<xsl:key name="kItemByStat"
match="item" use="status"/>
<!-- -->
<xsl:variable name="vDoc" select="/"/>
<xsl:template match="/">
<top>
<xsl:for-each select=
"/*/*/status[generate-id()
=
generate-id(key('kStatByVal',.)[1])
]">
<items>
<status><xsl:value-of select="."/></status>
<xsl:for-each select="key('kItemByStat', .)">
<xsl:copy-of select="name"/>
</xsl:for-each>
</items>
</xsl:for-each>
</top>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the original XML document:
<root>
<item>
<name>one</name>
<status>good</status>
</item>
<item>
<name>two</name>
<status>good</status>
</item>
<item>
<name>three</name>
<status>bad</status>
</item>
<item>
<name>four</name>
<status>ugly</status>
</item>
<item>
<name>five</name>
<status>bad</status>
</item>
</root>
The wanted result is produced:
<top>
<items>
<status>good</status>
<name>one</name>
<name>two</name>
</items>
<items>
<status>bad</status>
<name>three</name>
<name>five</name>
</items>
<items>
<status>ugly</status>
<name>four</name>
</items>
</top>
Do note the use of:
The Muenchian method for grouping
The use of <xsl:key> and the key() function
It depends about your xslt engine. If you're using xslt 1.0 without any extension, then your approach is certainly the best.
On the other side, if you're allowed to use exslt (especially the node-set extension) or xslt 2.0, then you could do it in a more generic way:
Collect all the available statuses
Create a node-set from the obtained result
Iterating on this node set, create your pivot by filtering you status base on the current element in your iteration.
But before doing that, consider that it may be overkill if you only have a few set of statuses and that adding another status is quite rare.
In XSLT 2.0 you can replace the muenchian grouping by its standard grouping mechanism. Applied to the given answer the xslt would look like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:key name="muench" match="/root/item/status" use="."/>
<xsl:template match="/">
<root>
<xsl:for-each-group select="/root/item/status" group-by="key('muench', .)">
<xsl:call-template name="pivot">
<xsl:with-param name="status" select="."/>
</xsl:call-template>
</xsl:for-each-group>
</root>
</xsl:template>
<xsl:template name="pivot">
<xsl:param name="status"/>
<items>
<status><xsl:value-of select="$status"/></status>
<xsl:for-each select="/root/item[status=$status]">
<name><xsl:value-of select="name"/></name>
</xsl:for-each>
</items>
</xsl:template>
</xsl:stylesheet>