XSLT: How to change attribute names as well? - xslt

This code is able to change elements to attribute key/value pairs. I want to change the attribute names in the same logic. How to do that?
Input:
<TESTSEQUENCE>
<TESTCASESTARTTIME>2014-05-02 16:02:38</TESTCASESTARTTIME>
<TESTCASENAME>TRAFFIC_MIXED_COLD_TP-A15 </TESTCASENAME>
<SCRIPTFILENAME>/proj/cpptemp/dt/network_repo/398/int/IEXS_CRX901185_1/iov/cbm1-3_mct/tc/Traffic.tcl</SCRIPTFILENAME>
<TXTLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15/TRAFFIC_MIXED_COLD_TP-A15.txt</TXTLOGFILENAME>
<HTMLLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15.html</HTMLLOGFILENAME>
<XMLLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15.xml</XMLLOGFILENAME>
<STARTTIME>1399039358</STARTTIME>
<TOTALCMDS>27</TOTALCMDS>
<NOTOKIDS>27</NOTOKIDS>
<NOTOKCMDS>{CETP ABORT}</NOTOKCMDS>
<FAILURESTRINGS>1=Failed,</FAILURESTRINGS>
<RESULT>ABORTED</RESULT>
<FINISHTIME>1399039672</FINISHTIME>
</TESTSEQUENCE>
Stylesheet:
<xsl:template match="TESTSEQUENCE">
<testcase>
<xsl:for-each select="*">
<xsl:attribute name="{name()}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</testcase>
</xsl:template>
Output:
<testcase time="2014-05-02 16:02:38" name="TRAFFIC_MIXED_COLD_TP-A15 " scriptfilename="mct/tc/Traffic.tcl" txtlogfilename="TRAFFIC_MIXED_COLD_TP-A15.txt" url="TRAFFIC_MIXED_COLD_TP-A15.html" xmllogfilename="TRAFFIC_MIXED_COLD_TP-A15.xml" starttime="1399039358" target_connect="" totalcmds="27" notokids="27" notokcmds="{CETP ABORT}" failurestrings="1=Failed," status="ABORTED" finishtime="1399039672">
</testcase>

Please enhance your code:
<xsl:template match="TESTSEQUENCE">
<testcase>
<xsl:for-each select="*">
<xsl:attribute name="{concat('ABC-',name())}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</testcase>
</xsl:template>
OR
<xsl:template match="TESTSEQUENCE">
<testcase>
<xsl:for-each select="*">
<xsl:attribute name="{if (name()) = 'TESTCASESTARTTIME' then 'TESTCASES' else ()}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</testcase>
</xsl:template>

TESTCASESTARTTIME to time TESTCASENAME to name HTMLLOGFILENAME to url
RESULT to status I need these 4 attributes to be changed
You need to exclude these 4 elements from the generic xsl:for-each applied to the other elements, and handle them explicitly:
XSLT 1.0
<?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" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="TESTSEQUENCE">
<testcase>
<xsl:for-each select="*[not (self::TESTCASESTARTTIME or self::TESTCASENAME or self::HTMLLOGFILENAME or self::RESULT)]">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:attribute name="time">
<xsl:value-of select="TESTCASESTARTTIME"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="TESTCASENAME"/>
</xsl:attribute>
<xsl:attribute name="url">
<xsl:value-of select="HTMLLOGFILENAME"/>
</xsl:attribute>
<xsl:attribute name="status">
<xsl:value-of select="RESULT"/>
</xsl:attribute>
</testcase>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Applied to your example input of:
<TESTSEQUENCE>
<TESTCASESTARTTIME>2014-05-02 16:02:38</TESTCASESTARTTIME>
<TESTCASENAME>TRAFFIC_MIXED_COLD_TP-A15</TESTCASENAME>
<SCRIPTFILENAME>/proj/cpptemp/dt/network_repo/398/int/IEXS_CRX901185_1/iov/cbm1-3_mct/tc/Traffic.tcl</SCRIPTFILENAME>
<TXTLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15/TRAFFIC_MIXED_COLD_TP-A15.txt</TXTLOGFILENAME>
<HTMLLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15.html</HTMLLOGFILENAME>
<XMLLOGFILENAME>TRAFFIC_MIXED_COLD_TP-A15.xml</XMLLOGFILENAME>
<STARTTIME>1399039358</STARTTIME>
<TOTALCMDS>27</TOTALCMDS>
<NOTOKIDS>27</NOTOKIDS>
<NOTOKCMDS>{CETP ABORT}</NOTOKCMDS>
<FAILURESTRINGS>1=Failed,</FAILURESTRINGS>
<RESULT>ABORTED</RESULT>
<FINISHTIME>1399039672</FINISHTIME>
</TESTSEQUENCE>
the result is:
<?xml version="1.0" encoding="UTF-8"?>
<testcase SCRIPTFILENAME="/proj/cpptemp/dt/network_repo/398/int/IEXS_CRX901185_1/iov/cbm1-3_mct/tc/Traffic.tcl" TXTLOGFILENAME="TRAFFIC_MIXED_COLD_TP-A15/TRAFFIC_MIXED_COLD_TP-A15.txt" XMLLOGFILENAME="TRAFFIC_MIXED_COLD_TP-A15.xml" STARTTIME="1399039358" TOTALCMDS="27" NOTOKIDS="27" NOTOKCMDS="{CETP ABORT}" FAILURESTRINGS="1=Failed," FINISHTIME="1399039672" time="2014-05-02 16:02:38" name="TRAFFIC_MIXED_COLD_TP-A15" url="TRAFFIC_MIXED_COLD_TP-A15.html" status="ABORTED"/>

Related

How do I copy text generated by my script to another section in my output file?

I need to copy the text generated by the code below to the <spine> area at the end of my output file. How can I accomplish that?
<xsl:attribute name="id">
<xsl:text>ppi</xsl:text>
<xsl:number format="0000" level="any"/>
</xsl:attribute>
This is my input:
<unit>
<chapter>
<exhibit path="chapter001/chapter01_reader01.html"/>
<exhibit path="chapter001/chapter01_reader02.html"/>
</chapter>
</unit>
This my desired output:
<manifest>
<item id="ppi0001" href="chapter001/chapter01_reader01.html" media-type="application/xhtml+xml"/>
<item id="ppi0002" href="chapter001/chapter01_reader02.html" media-type="application/xhtml+xml"/>
</manifest>
<spine>
<itemref idref="ppi0001" />
<itemref idref="ppi0002" />
</spine>
Here's my full script. I'm stuck at the line where it says <!--ID Generated in the "exhibit" template-->
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.idpf.org/2007/opf">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:element name="package" namespace="http://www.idpf.org/2007/opf">
<xsl:attribute name="unique-identifier">pub-id</xsl:attribute>
<xsl:attribute name="version">3.0</xsl:attribute>
<manifest>
<xsl:apply-templates select="//exhibit" />
</manifest>
<spine>
<xsl:element name="itemref">
<xsl:attribute name="idref">
<!--ID Generated in the "exhibit" template-->
</xsl:attribute>
</xsl:element>
</spine>
</xsl:element>
</xsl:template>
<xsl:template match="exhibit">
<xsl:element name="item">
<xsl:variable name="count" select="position()"/>
<xsl:attribute name="id">
<xsl:text>ppi</xsl:text>
<xsl:number format="0000" level="any"/>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="#path" />
</xsl:attribute>
<xsl:attribute name="media-type">
<xsl:text>application/xhtml+xml</xsl:text>
</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Thanks!
Here's a way you could accomplish this :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.idpf.org/2007/opf">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:element name="package" namespace="http://www.idpf.org/2007/opf">
<xsl:attribute name="unique-identifier">pub-id</xsl:attribute>
<xsl:attribute name="version">3.0</xsl:attribute>
<manifest>
<xsl:apply-templates select="//exhibit" />
</manifest>
<spine>
<xsl:apply-templates select="//exhibit" mode="spine"/>
</spine>
</xsl:element>
</xsl:template>
<xsl:template match="exhibit">
<xsl:element name="item">
<xsl:variable name="count" select="position()"/>
<xsl:attribute name="id">
<xsl:text>ppi</xsl:text>
<xsl:number format="0000" level="any"/>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="#path" />
</xsl:attribute>
<xsl:attribute name="media-type">
<xsl:text>application/xhtml+xml</xsl:text>
</xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="exhibit" mode="spine">
<xsl:element name="itemref">
<xsl:variable name="count" select="position()"/>
<xsl:attribute name="idref">
<xsl:text>ppi</xsl:text>
<xsl:number format="0000" level="any"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/6qaHaRT
Since you are reusing the #id for the itemref's I would use this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.idpf.org/2007/opf"
version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:element name="package" namespace="http://www.idpf.org/2007/opf">
<xsl:attribute name="unique-identifier">pub-id</xsl:attribute>
<xsl:attribute name="version">3.0</xsl:attribute>
<!-- first store the items in a variable -->
<xsl:variable name="items">
<!-- if you know the xpath to the exhibit, it is better for performence to make that explicit -->
<xsl:apply-templates select="unit/chapter/exhibit" />
</xsl:variable>
<manifest>
<!-- then copy those $items into the output -->
<xsl:copy-of select="$items"/>
</manifest>
<spine>
<!-- then reuse the $items for creating then itemref's-->
<xsl:apply-templates select="$items/*/#id" mode="spine"/>
</spine>
</xsl:element>
</xsl:template>
<xsl:template match="exhibit">
<xsl:element name="item">
<xsl:variable name="count" select="position()"/>
<xsl:attribute name="id">
<xsl:text>ppi</xsl:text>
<xsl:number format="0000" level="any"/>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="#path" />
</xsl:attribute>
<xsl:attribute name="media-type">
<xsl:text>application/xhtml+xml</xsl:text>
</xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="#id" mode="spine">
<xsl:element name="itemref">
<xsl:attribute name="idref">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

wrap XSLT result in a CDATA block

I doing an XSLT transformation.
input message:
<Accounts operation="query">
<Account operation="query">
<Home_spcPage>google.com</Home_spcPage>
<Id>1-NP8S</Id>
</Account>
</Accounts>
which should get transformed to :
<ipString>
<![CDATA[<Accounts operation="update" boNameVar="Account" bcNameVar="Account">
<Account operation="update">
<Home_spcPage>google.com</Home_spcPage>
<Id>1-NP8S</Id>
</Account>
</Accounts>]]>
</ipString>
I am trying with the below XSLT.
<xsl:stylesheet xmlns:crma="www.c123.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" method="xml"/>
<xsl:variable name="messageBlock">
<xsl:call-template name="main"/>
</xsl:variable>
<xsl:template match="/" name="main">
<xsl:apply-templates select="#*|node()"/>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:variable name="level" select="count(ancestor::node())"/>
<xsl:copy>
<xsl:choose>
<xsl:when test="$level=2">
<xsl:attribute name="operation">
<xsl:value-of select="'update'"/>
</xsl:attribute>
<xsl:variable name="currNodeVar" select="name()"/>
<xsl:if test="$currNodeVar='Account'">
<xsl:attribute name="boNameVar">Account</xsl:attribute>
<xsl:attribute name="bcNameVar">Account</xsl:attribute>
</xsl:if>
<xsl:if test="$currNodeVar='Contact'">
<xsl:attribute name="boNameVar">Contact</xsl:attribute>
<xsl:attribute name="bcNameVar">Contact</xsl:attribute>
</xsl:if>
</xsl:when>
<xsl:when test="$level=4">
<xsl:attribute name="operation">
<xsl:value-of select="'update'"/>
</xsl:attribute>
<xsl:variable name="currBCNameVar" select="name()"/>
<xsl:variable name="parBCNameVar" select="name(../..)"/>
</xsl:when>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:copy-of select="$messageBlock"/>
</xsl:template>
<xsl:template match="/">
<xsl:element name="ipString">
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="$messageBlock"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
but not getting the desired results . It seems like the XSLT is not considering the entire XML.
Any help is appreciated .
Thanks,
Naveen

jaxb transformerfactory xml to xml via xslt using generate-id for unique values

I have the following bit of code to transform one xml document into another via xslt
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(new javax.xml.transform.stream.StreamSource(
this.getClass().getClassLoader().getResourceAsStream(ie.getXslFileName())));
transformer.transform(
new javax.xml.transform.stream.StreamSource(reader),
new javax.xml.transform.stream.StreamResult(stream));
output.put(fileName, stream.toByteArray());
It works perfectly if I do not attempt to select disctinct values. However, as soon as I put in the generate-id line and key it fails. In every other test tool I use the transformation is perfect so I am thinking it is a limitation in jaxb's transformer? Does anyone have any suggestion as to how I can select unique values that will work here AND enable jaxb transformation? OR, alternatively, is there another transformer I could use that would do the trick?
XSLT that works everywhere BUT here:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" />
<xsl:key name="groupKey"
match="//questionGroup/externalCodes/externalCode/externalCode/text()"
use="." />
<xsl:template match="/">
<xsl:apply-templates select="submissionReport"/>
</xsl:template>
<xsl:template match="submissionReport" >
<component>
<structuredBody>
<xsl:for-each select="//questionResponse/question/questionGroup
/externalCodes/externalCode[governingBody
[internalCode='GVB-AHRQ-1']]
/externalCode/text()[generate-id() =
generate-id(key('groupKey',.)[1])]">
<component>
<section>
<entry>
<templateId>
<xsl:attribute name="root">
<xsl:value-of select="."/>
</xsl:attribute>
</templateId>
<organizer classCode="CLUSTER" moodCode="EVN">
<id nullFlavor="NA"/>
<statusCode code="completed"/>
<xsl:call-template name="groupedResponses">
<xsl:with-param name="groupInternalCode" select="."/>
</xsl:call-template>
</organizer>
</entry>
</section>
</component>
</xsl:for-each>
</structuredBody>
</component>
</xsl:template>
<xsl:template name="groupedResponses">
<xsl:param name="groupInternalCode"/>
<xsl:for-each select="//questionResponse[question[externalCodes
[externalCode[governingBody[internalCode='GVB-AHRQ-1'] and
not(externalCode='DE42') and not(externaCode='DE3') and
not(externalCode='DE46') and not(externalCode='DE49') and
not(externalCode='DE30')]] and
questionGroup[externalCodes[externalCode[governingBody[internalCode='GVB-AHRQ-1'] and
externalCode=$groupInternalCode]]]]]">
<component>
<observation>
<xsl:attribute name="classCode">OBS</xsl:attribute>
<xsl:attribute name="moodCode">EVN</xsl:attribute>
<templateId>
<xsl:attribute name="root">2.16.840.1.113883.3.263.1.11.3.100</xsl:attribute>
</templateId>
<xsl:for-each select="question/externalCodes/externalCode
[governingBody[internalCode='GVB-AHRQ-1'] or
governingBody[internalCode='GVB-CDCRACE-1'] or
governingBody[internalCode='GVB-HL7NULL-1'] or
governingBody[internalCode='GVB-HL7GENDER-1']]">
<!-- Question information -->
<code>
<xsl:attribute name="code">
<xsl:value-of select="externalCode"/>
</xsl:attribute>
<xsl:attribute name="displayName">
<xsl:value-of select="../../text"/>
</xsl:attribute>
<xsl:attribute name="codeSystem">
<xsl:value-of select="governingBody/externalCode"/>
</xsl:attribute>
<xsl:attribute name="codeSystemName">
<xsl:value-of select="governingBody/name"/>
</xsl:attribute>
</code>
<!-- Response information. Can be more than one -->
<xsl:for-each select="../../../response">
<value>
<xsl:choose>
<xsl:when test="responseOption">
<xsl:for-each select="responseOption/externalCodes/externalCode">
<value>
<xsl:attribute name="type">CD</xsl:attribute>
<xsl:attribute name="code">
<xsl:value-of select="externalCode"/>
</xsl:attribute>
<xsl:attribute name="displayName">
<xsl:value-of select="../../response"/>
</xsl:attribute>
<xsl:attribute name="codeSystem">
<xsl:value-of select="governingBody/externalCode"/>
</xsl:attribute>
<xsl:attribute name="codeSystemName">
<xsl:value-of select="governingBody/name"/>
</xsl:attribute>
</value>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<value>
<xsl:attribute name="type">ED</xsl:attribute>
<xsl:attribute name="mediaType">text/plain</xsl:attribute>
<xsl:value-of select="response"/>
</value>
</xsl:otherwise>
</xsl:choose>
</value>
</xsl:for-each>
</xsl:for-each>
</observation>
</component>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I decided to go with importing Saxon to enable XSLT 2.0. Seconds later grouping is perfect and works easily.

XSLT removing unnecessary element

i am trying to write an xslt code that will check whether the description element exist or not if it exist then it will show the description element but if it does not exist then it should not show the description element.but my code below still show element although there is no value in it.how can we code it so that it wont show out the description element if there is no description for a services.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Service">
<xsl:element name="equipment">
<xsl:if test="description !='' ">
<xsl:value-of select="description" />
</xsl:if>
<xsl:if test="not(description)">
</xsl:if>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
as there is the an empty equipment element being returned.i want it to return only the first 2 equipment element that is not empty.
Updated solution is follows; please check
<xsl:template match="Services">
<xsl:for-each select="Service">
<xsl:if test="count(description) > 0 and description!=''">
<equipment>
<xsl:value-of select="description"/>
</equipment>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="/">
<xsl:apply-templates select="//Service"/>
</xsl:template>
<xsl:template match="Service">
<xsl:if test="description !='' ">
<xsl:element name="equipment">
<xsl:value-of select="description" />
</xsl:element>
</xsl:if>
</xsl:template>
or
<xsl:template match="/">
<xsl:apply-templates select="//Service"/>
</xsl:template>
<xsl:template match="Service">
<xsl:if test="child::description[text()]">
<xsl:element name="equipment">
<xsl:value-of select="description" />
</xsl:element>
</xsl:if>
</xsl:template>
Does this work for you?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- place <result /> as root to produce wellformed XML -->
<xsl:template match="/">
<result><xsl:apply-templates /></result>
</xsl:template>
<!-- rewrite those <Service /> that have a <description /> -->
<xsl:template match="Service[./description]">
<equipment><xsl:value-of select="description" /></equipment>
</xsl:template>
<!-- remove those who do not -->
<xsl:template match="Service[not(./description)]" />
</xsl:transform>

xslt aggregation sum

I want do some sum of the values and return it as a row or column with the data.
taking the below xml as example:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<root>
<default0>
<Group>
<groupEntry>
<Day>Mon</Day>
<ID>111</ID>
<Number>-3</Number>
</groupEntry>
</Group>
<Group>
<groupEntry>
<Day>Tue</Day>
<ID>222</ID>
<Number>4</Number>
</groupEntry>
</Group>
<Group>
<groupEntry>
<Day>Tue</Day>
<ID>444</ID>
<Number>5</Number>
</groupEntry>
<Breakdown>
<Details>
<Day>Tue</Day>
<ID>444</ID>
<Number>-3</Number>
</Details>
<Details>
<Day>Tue</Day>
<ID>444</ID>
<Number>8</Number>
</Details>
</Breakdown>
</Group>
<Group>
<groupEntry>
<Day>Fri</Day>
<ID>333</ID>
<Number>-3</Number>
</groupEntry>
</Group>
</default0>
</root>
My below xslt :
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>ID,Day,Number</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="groupEntry|Details">
<xsl:text>
</xsl:text>
<xsl:value-of select="ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Day"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Number"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
returns this result:
ID,Day,Number
111,Mon,-3
222,Tue,4
444,Tue,5
444,Tue,-3
444,Tue,8
333,Fri,-3
However I want to get the total number by Day and report it in the result as either of the below 2 options
create 1 summary row like:
ID,Day,Number
Mon,Mon,-3
111,Mon,-3
Tue,Tue,9
222,Tue,4
444,Tue,5
444,Tue,-3
444,Tue,8
Fri,Fri,-3
333,Fri,-3
create an extra column:
ID,Day,Number,TotalNumber
111,Mon,-3,-3
222,Tue,4,9
444,Tue,5,9
444,Tue,-3,9
444,Tue,8,9
333,Fri,-3,-3
Does anyone know if this is possible?
In either option, you would probably need to define a key to group the elements by Day
<xsl:key name="days" match="groupEntry|Details" use="Day"/>
Then you can just add your extra column like so
<xsl:value-of select="sum(key('days', Day)/Number)"/>
Here is the full XSLT for the first option
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="days" match="groupEntry|Details" use="Day"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>ID,Day,Number,TotalNumber</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="groupEntry|Details">
<xsl:text>
</xsl:text>
<xsl:value-of select="ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Day"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Number"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="sum(key('days', Day)/Number)"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
This should output the following results
ID,Day,Number,TotalNumber
111,Mon,-3,-3
222,Tue,4,14
444,Tue,5,14
444,Tue,-3,14
444,Tue,8,14
333,Fri,-3,-3
In the second option, you would want to add a total line for the first occurrence of a particular Day. You can do this by checking if the current element is the first element in the key for that day
<xsl:if test="generate-id() = generate-id(key('days', Day)[1])">
Here is the XSLT for the second case
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="days" match="groupEntry|Details" use="Day"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>ID,Day,Number</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="groupEntry|Details">
<xsl:if test="generate-id() = generate-id(key('days', Day)[1])">
<xsl:text>
</xsl:text>
<xsl:value-of select="Day"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Day"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="sum(key('days', Day)/Number)"/>
</xsl:if>
<xsl:text>
</xsl:text>
<xsl:value-of select="ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Day"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="Number"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
This should output the following results
ID,Day,Number
Mon,Mon,-3
111,Mon,-3
Tue,Tue,14
222,Tue,4
444,Tue,5
444,Tue,-3
444,Tue,8
Fri,Fri,-3
333,Fri,-3