I have the following input
<?xml version="1.0" encoding="UTF-8"?>
<document>
<body>
<p>
<pPr>
<spacing after="120"/>
<ind left="357"/>
</pPr>
<r>
<t>Should stay same</t>
</r>
</p>
<p>
<pPr>
<pStyle val="ListeAufzhlung"/>
<spacing after="120"/>
</pPr>
<r>
<t>Liste.Aufzählung</t>
</r>
</p>
<p>
<pPr>
<spacing after="120"/>
<ind left="357"/>
</pPr>
<r>
<t>Shouldl change ind to pStyle</t>
</r>
</p>
<p>
<pPr>
<pStyle val="ListeAufzhlung2"/>
<spacing after="120"/>
</pPr>
<r>
<t>Liste.Aufzählung 2</t>
</r>
</p>
</body>
</document>
My desired outcome:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<body>
<p>
<pPr>
<spacing after="120"/>
<ind left="357"/>
</pPr>
<r>
<t>Should stay same</t>
</r>
</p>
<p>
<pPr>
<pStyle val="ListeAufzhlung"/>
<spacing after="120"/>
</pPr>
<r>
<t>Liste.Aufzählung</t>
</r>
</p>
<p>
<pPr>
<spacing after="120"/>
<pStyle val="ListeAufzhlung"/>
</pPr>
<r>
<t>Shouldl change ind to pStyle</t>
</r>
</p>
<p>
<pPr>
<pStyle val="ListeAufzhlung2"/>
<spacing after="120"/>
</pPr>
<r>
<t>Liste.Aufzählung 2</t>
</r>
</p>
</body>
</document>
Logic:
If there is an ind-tag were in the previous p-node is and pStyle with val "ListeAufzhlung", change the ind tag to <pStyle val="ListeAufzhlung"/>. The val can differ too. So if the condition is true, replace the current ind-tag with the pStyle-tag from previous p-tag.
My xslt so far:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="t"/>
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="no"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ind[#left]">
</xsl:template>
</xsl:stylesheet>
Following doesnt work:
<xsl:template match="ind[#left] and ../../p/pPr/pStyle[#val="ListeAufzhlung"]">
Anyone got a good solution for this?
I think you can check
<xsl:template match="p[pPr/ind[#left]][preceding-sibling::*[1][self::p[pPr/pStyle/#val = 'ListeAufzhlung']]]/pPr/ind">
<pStyle val="ListeAufzhlung"/>
</xsl:template>
or
<xsl:template match="p[pPr/ind[#left]][preceding-sibling::*[1][self::p[pPr/pStyle/#val]]]/pPr/ind">
<xsl:copy-of select="ancestor::p/preceding-sibling::*[1]/pPr/pStyle[#val]"/>
</xsl:template>
for the more general case.
Related
I would like to select Parent node without Child node.
Example:
<root>
<p>some text</p>
<ol>
<li>
http://cowherd.com
</li>
</ol>
<p> http://cowherd.com </p>
http://cowherd.com
</root>
Desired Output: I want to add a parent <p> tag to those <a> tags which don't have any parent except <root>.
<root>
<p>some text</p>
<ol>
<li>
http://cowherd.com
</li>
</ol>
<p> http://cowherd.com </p>
<p> http://cowherd.com <p>
</root>
I tried thi but it doesn't work. It adds the <p> tag around all <a> tags.
<xsl:template match="a">
<xsl:if test="parent::*">
<p><a>
<!-- do not forget to copy possible other attributes -->
<xsl:apply-templates select="#* | node()"/>
</a></p>
</xsl:if>
</xsl:template>
I want to add a parent <p> tag to those <a> tags which don't have any parent except <root>.
I believe that boils down to:
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"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/a">
<p>
<xsl:copy-of select="."/>
</p>
</xsl:template>
</xsl:stylesheet>
Here's a way this could be done :
<?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="a[not(parent::p)]">
<p>
<xsl:copy-of select="."/>
</p>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/93F8dVt
I have <r> tags within a <p> tag. Each <r>-Tag can have attributes within and has a <t>-Tag.
I need to combine those t-tags into one but edit bevor doing so.
Example input:
<document>
<body>
<p>
<r>
<rPr>
<rStyle val="TabelleSpaltentitelZchn"/>
</rPr>
<t>Erster Teil</t>
</r>
<r>
<t space="preserve"> Zweiter Teil</t>
</r>
</p>
</body>
</document>
Desired outcome:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<body>
<p>
<r>
<t><span class="TabelleSpaltentitelZchn">Erster Teil</span> Zweiter Teil</t>
</r>
</p>
</body>
</document>
So at each <r>-Tag which contains a rStyle-Information, i need to wrap the <t>-Value into a span.
My xslt so far:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:preserve-space elements="t"/>
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="no"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/r[1]">
<r>
<t><xsl:value-of separator="" select="../r/t"/></t>
</r>
</xsl:template>
<xsl:template match="p/r[position() gt 1]"/>
</xsl:stylesheet>
This works fine to just combine those <t>-Tags. But i have no clue how to edit them befor.
Write templates for the t elements:
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/r[1]">
<r>
<t>
<xsl:apply-templates select="../r/t"/>
</t>
</r>
</xsl:template>
<xsl:template match="p/r[rPr/rStyle/#val]/t">
<span class="{../rPr/rStyle/#val}">
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="p/r[not(rPr/rStyle/#val)]/t">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="p/r[position() gt 1]"/>
I have the following xml:
<?xml version="1.0" encoding="UTF-8"?>
<Test xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lab="urn:oid:7.6">
<section>
<id extension="something" root="testRoot"/>
<text>
<paragraph styleCode="somestyle">Soemthing</paragraph>
<table>
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</text>
</section>
</Test>
and this is the xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="#all">
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match = "c:section/ c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>
This is the output:
<?xml version="1.0" encoding="UTF-8"?><Test>
<section>
<id extension="something" root="testRoot"/>
<text><status value="generated"/><div xmlns="http://www.w3.org/1999/xhtml">
<paragraph xmlns="" styleCode="somestyle">Soemthing</paragraph>
<table xmlns="">
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div></text>
</section>
</Test>
As you might expect, I don't want any of those empty namespaces like in paragraph and table. I want to get rid of them so that those elements are just as they are without any namespaces but the div element should retain the namespace.
EDIT: I also would like to get rid of the attributes (including their values) for all elements under text. So that final output looks like this:
<?xml version="1.0" encoding="UTF-8"?><Test>
<section>
<id extension="something" root="testRoot"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<paragraph>Soemthing</paragraph>
<table>
<thead>
<tr>
<th>Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div>
</text>
</section>
</Test>
I am guessing (!) you want to do:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
exclude-result-prefixes="c">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="xhtml" >
<xsl:element name="{local-name(.)}" namespace="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="#* | node()" mode="xhtml"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*" mode="#all">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="c:section/c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>
This will place all descendants of div into the same xhtml namespace as their ancestor - resulting in:
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<section>
<id extension="something" root="testRoot"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<paragraph styleCode="somestyle">Soemthing</paragraph>
<table>
<thead>
<tr>
<th styleCode="styled">Style</th>
<th>Stuff</th>
</tr>
</thead>
</table>
</div>
</text>
</section>
</Test>
Note that this is not valid XHTML markup.
Edit
I also would like to get rid of the attributes (including their
values) for all elements under text.
Well, then don't apply templates to them:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="urn:hl7-org:v3"
exclude-result-prefixes="c">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="xhtml" >
<xsl:element name="{local-name(.)}" namespace="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="c:section/c:text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates mode="xhtml"/>
</div>
</text>
</xsl:template>
</xsl:stylesheet>
Good Day,
I have an xml file that looks like:
<albums xmlns="http://www.someurl.com/schema">
<album>
<artist>Rush</artist>
<name>Moving Pictures</name>
<releaseDate>05-31-1981</releaseDate>
<album>
</albums>
what I want is to use xlst to display the artist, name, and how many years is been since the release date.
<div id="recordInfo">
<div class="col"><xsl:value-of select="/t:albums/t:album/t:artist"></div>
<div class="col"><xsl:value-of select="/t:albums/t:album/t:name"></div>
<!-- I want the value of 31 here -->
</div>
Does anyone have any idea of how to do that in XSLT?
TIA,
coson
This transformation:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vTokens" select="tokenize(/*, '-')"/>
<xsl:variable name="vDate" select=
"string-join(($vTokens[3], $vTokens[1], $vTokens[2]), '-')"/>
<xsl:template match="/*">
<xsl:sequence select=
"floor((current-date() - xs:date($vDate)) div xs:dayTimeDuration('P365D')) "/>
</xsl:template>
</xsl:stylesheet>
When applied on this XML document:
<t>05-31-1981</t>
produces the wanted, correct result:
31
Here's an XSLT 2.0 option...
XML Input
<albums xmlns="http://www.someurl.com/schema">
<album>
<artist>Rush</artist>
<name>Moving Pictures</name>
<releaseDate>05-31-1981</releaseDate>
</album>
</albums>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://www.someurl.com/schema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="albums">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="t:album">
<div id="recordInfo">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="t:artist|t:name">
<div class="col"><xsl:value-of select="."/></div>
</xsl:template>
<xsl:template match="t:releaseDate">
<xsl:variable name="vOrigDate" select="tokenize(.,'-')"/>
<xsl:variable name="vDate" select="xs:date(concat($vOrigDate[3],'-',$vOrigDate[1],'-',$vOrigDate[2]))" as="xs:date"/>
<div class="col"><xsl:value-of select="floor(days-from-duration(current-date() - $vDate) div 365)"/></div>
</xsl:template>
</xsl:stylesheet>
Output
<div id="recordInfo">
<div class="col">Rush</div>
<div class="col">Moving Pictures</div>
<div class="col">31</div>
</div>
This XSLT 1.0 template...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://www.someurl.com/schema"
exclude-result-prefixes="xsl t" >
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="current-year" select="2012" />
<xsl:template match="/">
<r>
<xsl:apply-templates select="t:albums/t:album" />
</r>
</xsl:template>
<xsl:template match="t:album">
<div id="recordInfo">
<div class="col"><xsl:value-of select="t:artist" /></div>
<div class="col"><xsl:value-of select="t:name" /></div>
<div class="col"><xsl:value-of select="$current-year - substring(t:releaseDate,7)" /></div>
</div>
</xsl:template>
</xsl:stylesheet>
...will yield this output...
<r>
<div id="recordInfo">
<div class="col">Rush</div>
<div class="col">Moving Pictures</div>
<div class="col">31</div>
</div>
</r>
I've used a variable to store the date. In practice you will use a function to get the current date. Which function depends on XSLT version and engine.
I have the following simplified XML structure:
<?xml version="1.0" encoding="UTF-8"?>
<ExportData>
<DataSet>
<Tables>
<Table>
<Rows>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9991</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9992</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9994</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9995</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue/>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
</Rows>
</Table>
</Tables>
</DataSet>
</ExportData>
I need to group the recordset (R) depending on the "Qualifierstring" and the "revenueCenter". I came up with this XSLT which works perfectly:
<?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="text()|#*"/>
<!-- define the key to define unique elements -->
<xsl:key name="keyTranstypeCcRc" match="R" use="concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue)"/>
<!-- define which elements are unique -->
<xsl:template match="ExportData/DataSet/Tables/Table/Rows">
<xsl:variable name="uniqueTransactions" select="R[generate-id()=generate-id(key('keyTranstypeCcRc',concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue))[1])]"/>
<ExportData>
<xsl:apply-templates select="$uniqueTransactions" mode="group"/>
</ExportData>
</xsl:template>
<!-- create the unique groups -->
<xsl:template match="R" mode="group">
<transaction>
<xsl:attribute name="transactionType"><!-- write the 2 key criteria into this attribute -->
<xsl:value-of select="concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue)"/>
</xsl:attribute>
<xsl:apply-templates select="key('keyTranstypeCcRc', concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue))" mode="item"/>
</transaction>
</xsl:template>
<!-- write the item content into each group -->
<xsl:template match="R" mode="item">
<R>
<xsl:copy-of select="child::*"/>
</R>
</xsl:template>
</xsl:stylesheet>
I define a key and select unique items, build the groups and process the recordsets (R).
But now how could I define the key so I am grouping "revenueCenter" 9992 and 9993 together?
Do I have to set up 2 different keys? (but how could I use 2 keys with my templates)
Or can I extend the existing key with values?
The XML should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<ExportData>
<transaction transactionType="Sales|9991">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9991</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|9993 Sales|9992">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9992</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|9994">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9994</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|9995">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9995</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue/>
</R>
</transaction>
</ExportData>
24th May 2012 UPDATE:
I actually came up with an XSLT that does what I want, I am using two different keys:
<?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="text()|#*"/>
<!-- define the key to define unique elements -->
<!--<xsl:key name="keyTranstypeCcRc" match="R" use="concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue)"/>-->
<xsl:key name="keyTranstypeCcRc" match="R[not(revenueCenterPOSReflongtrue='9992' or revenueCenterPOSReflongtrue='9993')]"
use="concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue)"/>
<xsl:key name="keyTranstypeCcRc99923" match="R[revenueCenterPOSReflongtrue='9992' or revenueCenterPOSReflongtrue='9993']"
use="transactionQualifierstring"/>
<!-- define which elements are unique -->
<xsl:template match="ExportData/DataSet/Tables/Table/Rows">
<xsl:variable name="uniqueTransactions" select="R[not(revenueCenterPOSReflongtrue='9992' or revenueCenterPOSReflongtrue='9993')]
[generate-id()=generate-id(key('keyTranstypeCcRc',concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue))[1])]"/>
<xsl:variable name="keyTranstypeCcRc99923" select="R[revenueCenterPOSReflongtrue='9992' or revenueCenterPOSReflongtrue='9993']
[generate-id()=generate-id(key('keyTranstypeCcRc99923',transactionQualifierstring)[1])]"/>
<ExportData>
<xsl:apply-templates select="$uniqueTransactions" mode="group"/>
<xsl:apply-templates select="$keyTranstypeCcRc99923" mode="group99923"/>
</ExportData>
</xsl:template>
<!-- create the unique groups -->
<xsl:template match="R" mode="group">
<transaction>
<xsl:attribute name="transactionType"><!-- write the 2 key criteria into this attribute -->
<xsl:value-of select="concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue)"/>
</xsl:attribute>
<xsl:apply-templates select="key('keyTranstypeCcRc', concat(transactionQualifierstring,'|',revenueCenterPOSReflongtrue))" mode="item"/>
</transaction>
</xsl:template>
<!-- create the unique groups -->
<xsl:template match="R" mode="group99923">
<transaction>
<xsl:attribute name="transactionType"><!-- write the 2 key criteria into this attribute -->
<xsl:value-of select="concat(transactionQualifierstring,'|','9992','|','9993')"/>
</xsl:attribute>
<xsl:apply-templates select="key('keyTranstypeCcRc99923', transactionQualifierstring)" mode="item"/>
</transaction>
</xsl:template>
<!-- write the item content into each group -->
<xsl:template match="R" mode="item">
<R>
<xsl:copy-of select="child::*"/>
</R>
</xsl:template>
</xsl:stylesheet>
Applied to the source XML I get this correct output:
<?xml version="1.0" encoding="UTF-8"?>
<ExportData>
<transaction transactionType="Sales|9991">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9991</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|9994">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9994</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|9995">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9995</revenueCenterPOSReflongtrue>
</R>
</transaction>
<transaction transactionType="Sales|">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue/>
</R>
</transaction>
<transaction transactionType="Sales|9992|9993">
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9992</revenueCenterPOSReflongtrue>
</R>
<R>
<transactionQualifierstring>Sales</transactionQualifierstring>
<revenueCenterPOSReflongtrue>9993</revenueCenterPOSReflongtrue>
</R>
</transaction>
</ExportData>
This solution works because I know which values I need to exclude and group seperately.
Any time you want things sorted and/or grouped in a particular manner it helps to think of generating a "sort key". At the point where you generate the index
<xsl:key name="keyTranstypeCcRc" match="R" use="makeKey(...)"/>
you need to provide a function that generates the desired key from the appropriate arguments. You then use the same function when looking up keys in the index.
In XSLT 1 you could use the EXSLT func:function to package the logic reusably.
If you're familiar with Java, this is kind of like defining a custom Comparator.