XSLT question - Transpose multiple columns to rows - xslt-2.0

I have an xml that needs one row (report_entry) split into multiple columns. The columns starting from wd:W2_401k through wd:W2_Uncollected_Social_Security_Tax_Tipsneed to be split into 17 columns. The approach I know is to use a for-each wd:report_entry, use 17 templates and define common fields repetitively. Is there an efficient way to do this? I have posted my xslt for 3 row split, need to it for 17 rows though.
<?xml version="1.0" encoding="UTF-8"?>
<wd:Report_Data xmlns:wd="urn:com.workday.report/ERP-PAY-CR_PAYROLL_BALANCES_SUMMARY_W2">
<wd:Report_Entry>
<wd:Country>US</wd:Country>
<wd:Entity_Name>BalanceInitialization</wd:Entity_Name>
<wd:Legislative_Data>US Care LDG</wd:Legislative_Data>
<wd:Legal_Entity_Name>Wayne Industries</wd:Legal_Entity_Name>
<wd:Person_Number>2188941</wd:Person_Number>
<wd:Effective_As_of_Date>2020-01-01</wd:Effective_As_of_Date>
<wd:Assignment_Number>2188946-04272015E01</wd:Assignment_Number>
<wd:W2_401k>7062.6</wd:W2_401k>
<wd:W2_Roth_401k>0</wd:W2_Roth_401k>
<wd:W2_457>0</wd:W2_457>
<wd:W2_Health_Saving_Account>0</wd:W2_Health_Saving_Account>
<wd:W2_BOX_14A_-_CASDI>1229.09</wd:W2_BOX_14A_-_CASDI>
<wd:W2_BOX_14B_-_FOUND>0</wd:W2_BOX_14B_-_FOUND>
<wd:W2_BOX_14C_-_UWAY>0</wd:W2_BOX_14C_-_UWAY>
<wd:W2_BOX_14D_-_TRANSP>0</wd:W2_BOX_14D_-_TRANSP>
<wd:W2_BOX_14E_-_UNION_DUE>0</wd:W2_BOX_14E_-_UNION_DUE>
<wd:W2_BOX_14F_-_HCRA>1000</wd:W2_BOX_14F_-_HCRA>
<wd:W2_BOX_14G_-_EMPCMPGN>125</wd:W2_BOX_14G_-_EMPCMPGN>
<wd:W2_Dependent_Care>0</wd:W2_Dependent_Care>
<wd:W2_Group_Term_Life>0</wd:W2_Group_Term_Life>
<wd:W2_Health_Coverage>6970</wd:W2_Health_Coverage>
<wd:W2_Qualified_Move>0</wd:W2_Qualified_Move>
<wd:W2_Uncollected_Medicare_Tips>0</wd:W2_Uncollected_Medicare_Tips>
<wd:W2_Uncollected_Social_Security_Tax_Tips>0</wd:W2_Uncollected_Social_Security_Tax_Tips>
<wd:Upload_Date>2020-01-01</wd:Upload_Date>
<wd:Dimension>Relationship Tax Unit Year To Date</wd:Dimension>
<wd:PR_Relationship>2188946</wd:PR_Relationship>
<wd:Legal_Employer>St. Joseph Health System</wd:Legal_Employer>
<wd:Payroll wd:Descriptor="Biweekly A">
<wd:ID wd:type="WID">2af036de57bc01be1ff6752d9a18f5c6</wd:ID>
<wd:ID wd:type="Evaluate_Expression_Band_Related_Content_Reference_ID">EVALUATE_EXPRESSION_BAND_CALCULATED_FIELD_RELATED_CONTENT-6-505</wd:ID>
</wd:Payroll>
<wd:Tax_Reporting_Unit>Wayne Corporation</wd:Tax_Reporting_Unit>
</wd:Report_Entry>
</wd:Report_Data>
Xslt:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday.report/ERP-PAY-CR_PAYROLL_BALANCES_SUMMARY_W2">
<xsl:output method="text"/>
<xsl:variable name="linefeed" select="'
'"/>
<xsl:variable name="pipe" select="'|'"/>
<xsl:param name="quote">"</xsl:param>
<xsl:template match="/wd:Report_Data">
<xsl:for-each select="wd:Report_Entry">
<xsl:call-template name="W2_401k">
</xsl:call-template>
<xsl:call-template name="W2_Roth_401k">
</xsl:call-template>
<xsl:call-template name="W2_457">
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="W2_401k">
<xsl:value-of select="wd:Country"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legislative_Data"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legal_Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Person_Number"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Assignment_Number"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="format-number(wd:W2_401k,'#.00')"/>
<xsl:value-of select="$pipe"/>
<!-- Upload Date Place Holder -->
<xsl:value-of select="wd:Upload_Date"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Dimension"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Person_Number"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Payroll/#wd:Descriptor"/>
<xsl:value-of select="wd:Area_One"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<!-- Balance Date Place Holder -->
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Tax_Reporting_Unit"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="$linefeed"/>
</xsl:template>
<xsl:template name="W2_Roth_401k">
<xsl:value-of select="wd:Country"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legislative_Data"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legal_Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Person_Number"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Assignment_Number"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="format-number(wd:W2_Roth_401k,'#.00')"/>
<xsl:value-of select="$pipe"/>
<!-- Upload Date Place Holder -->
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Dimension"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Person_Number"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Payroll/#wd:Descriptor"/>
<xsl:value-of select="wd:Area_One"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<!-- Balance Date Place Holder -->
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Tax_Reporting_Unit"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="$linefeed"/>
</xsl:template>
<xsl:template name="W2_457">
<xsl:value-of select="wd:Country"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legislative_Data"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Legal_Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Person_Number"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="wd:Assignment_Number"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="format-number(wd:W2_457,'#.00')"/>
<xsl:value-of select="$pipe"/>
<!-- Upload Date Place Holder -->
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Dimension"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Person_Number"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Payroll/#wd:Descriptor"/>
<xsl:value-of select="wd:Area_One"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<!-- Balance Date Place Holder -->
<xsl:value-of select="wd:Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="wd:Tax_Reporting_Unit"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="$linefeed"/>
</xsl:template>
</xsl:stylesheet>

I would at least try to shorten the code like this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday.report/ERP-PAY-CR_PAYROLL_BALANCES_SUMMARY_W2"
xpath-default-namespace="urn:com.workday.report/ERP-PAY-CR_PAYROLL_BALANCES_SUMMARY_W2">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:param name="linefeed" select="'
'"/>
<xsl:param name="pipe" select="'|'"/>
<xsl:param name="quote">"</xsl:param>
<xsl:template match="Report_Entry">
<xsl:variable name="entry" select="."/>
<xsl:for-each select="W2_401k, W2_Roth_401k, W2_457">
<xsl:apply-templates select="$entry" mode="transpose">
<xsl:with-param name="col" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="Report_Entry" mode="transpose">
<xsl:param name="col"/>
<xsl:value-of select="Country"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Legislative_Data"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Legal_Entity_Name"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Person_Number"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Effective_As_of_Date"/>
<xsl:value-of select="$pipe"/>
<xsl:value-of select="Assignment_Number"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="format-number($col,'#.00')"/>
<xsl:value-of select="$pipe"/>
<!-- Upload Date Place Holder -->
<xsl:value-of select="Upload_Date"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="Dimension"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Person_Number"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="Payroll/#wd:Descriptor"/>
<xsl:value-of select="Area_One"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<!-- Balance Date Place Holder -->
<xsl:value-of select="Effective_As_of_Date"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Tax_Reporting_Unit"/>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:text>|</xsl:text>
<xsl:value-of select="$linefeed"/>
</xsl:template>
</xsl:stylesheet>
And XSLT 2.0 has an xsl:value-of select="sequence-expression" separator="{$pipe}" that might help to reduce the verbosity of all your separate xsl:value-of, xsl:value-of select="$pipe" but I haven't tried to identify which "empty" cols you want or need to spell that out exactly, but along the lines of
<xsl:template match="Report_Entry" mode="transpose">
<xsl:param name="col"/>
<xsl:value-of
select="Country, Entity_Name, Legislative_Data, Legal_Entity_Name, Person_Number,
Effective_As_of_Date, Assignment_Number,
format-number($col,'#.00'),
Upload_Date,
'', '',
Dimension, PersonNumber,
'', '', '', '',
Payroll/#wd:Descriptor, Area_One,
'', '', '', '', '', '', '',
Effective_As_of_Date, Tax_Reporting_Unit,
(1 to 10) ! ''"
separator="{$pipe}"/>
<xsl:value-of select="$linefeed"/>
</xsl:template>

Related

Find and replace for the particular texts within same text() node, more than once

Please suggest to find replace the required text within one text() node, some times find-replace text repeated more than once.
Here, scripts should exclue the element '<p>'. Working fine when 'find' text occuring only once in a text node, if it occures more than once, then skipping the replace process (see first <p1>). Please suggest.
XML:
<article>
<p1>The text 1111, 2222, 3333 and 4444 are some values, 1111 another occurance.</p1>
<p1>The text 1111, 2222, 3333 and 4444 are some values</p1>
<p>The text 1111, 2222, 3333 and 4444 are some values</p>
<p1>The text aaaaa, bbbbb, ccccc and ddddd are another set of values</p1>
<p1>The text <i>aaaaa</i>, <b>bbbbb</b> and <c>ccccc</c> are in different form</p1>
</article>
XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#* | node()"/></xsl:copy>
</xsl:template>
<xsl:template match="*/text()">
<xsl:call-template name="tempFindReplace">
<xsl:with-param name="pText1" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="tempFindReplace">
<xsl:param name="pText1"/>
<xsl:if test="string-length($pText1) > 0">
<xsl:choose>
<xsl:when test="ancestor::p1">
<xsl:choose>
<xsl:when test="contains($pText1, '1111')">
<xsl:value-of select="substring-before($pText1,'1111')"/><xsl:text>Alpha1</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '1111')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '2222')">
<xsl:value-of select="substring-before($pText1,'2222')"/><xsl:text>Alpha2</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '2222')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '3333')">
<xsl:value-of select="substring-before($pText1,'3333')"/><xsl:text>Alpha3</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '3333')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '4444')">
<xsl:value-of select="substring-before($pText1,'4444')"/><xsl:text>Alpha4</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '4444')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'aaaaa')">
<xsl:value-of select="substring-before($pText1,'aaaaa')"/><xsl:text>Beta1</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'aaaaa')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'bbbbb')">
<xsl:value-of select="substring-before($pText1,'bbbbb')"/><xsl:text>Beta2</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'bbbbb')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'ccccc')">
<xsl:value-of select="substring-before($pText1,'ccccc')"/><xsl:text>Beta3</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ccccc')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'ddddd')">
<xsl:value-of select="substring-before($pText1,'ddddd')"/><xsl:text>Beta4</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ddddd')"/></xsl:call-template></xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($pText1,1,1)"/>
<xsl:call-template name="tempFindReplace">
<xsl:with-param name="pText1" select="substring($pText1, 2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Required Result:
<article>
<p1>The text Alpha1, Alpha2, Alpha3 and Alpha4 are some values, Alpha1 another occurance.</p1><!-- Alpha1 only replacing, but other texts also required change, I assume here failing because of 1111 appearing twice-->
<p1>The text Alpha1, Alpha2, Alpha3 and Alpha4 are some values</p1>
<p>The text 1111, 2222, 3333 and 4444 are some values</p>
<p1>The text Beta1, Beta2, Beta3 and Beta4 are another set of values</p1>
<p1>The text <i>Beta1</i>, <b>Beta2</b> and <c>Beta3</c> are in different form</p1>
</article>
I continue to think you can use the replace function repeatedly, for instance in XSLT 3 with xsl:iterate:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="replacements" as="array(xs:string)*"
select="['1111', 'Alpha1'], ['2222', 'Alpha2'], ['3333', 'Alpha3'], ['4444', 'Alpha4'],
['aaaaa', 'Beta1'], ['bbbbb', 'Beta2'], ['ccccc', 'Beta3'], ['ddddd', 'Beta4'] "/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="article/*[not(self::p)]//text()">
<xsl:iterate select="$replacements">
<xsl:param name="text" select="."/>
<xsl:on-completion>
<xsl:value-of select="$text"/>
</xsl:on-completion>
<xsl:next-iteration>
<xsl:with-param name="text" select="replace($text, .(1), .(2))"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bwdwrL
XSLT 2:
called template twice, and got the result.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#* | node()"/></xsl:copy>
</xsl:template>
<xsl:template match="*[ancestor-or-self::*[matches(name(), '^(p1|p2|p3)$')]]/text()">
<xsl:variable name="var1">
<xsl:call-template name="tempFindReplace">
<xsl:with-param name="pText1" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="tempFindReplace">
<xsl:with-param name="pText1" select="$var1"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="tempFindReplace">
<xsl:param name="pText1"/>
<xsl:if test="string-length($pText1) > 0">
<xsl:choose>
<xsl:when test="contains($pText1, '1111')">
<xsl:value-of select="substring-before($pText1,'1111')"/><xsl:text>Alpha1</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '1111')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '2222')">
<xsl:value-of select="substring-before($pText1,'2222')"/><xsl:text>Alpha2</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '2222')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '3333')">
<xsl:value-of select="substring-before($pText1,'3333')"/><xsl:text>Alpha3</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '3333')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, '4444')">
<xsl:value-of select="substring-before($pText1,'4444')"/><xsl:text>Alpha4</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, '4444')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'aaaaa')">
<xsl:value-of select="substring-before($pText1,'aaaaa')"/><xsl:text>Beta1</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'aaaaa')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'bbbbb')">
<xsl:value-of select="substring-before($pText1,'bbbbb')"/><xsl:text>Beta2</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'bbbbb')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'ccccc')">
<xsl:value-of select="substring-before($pText1,'ccccc')"/><xsl:text>Beta3</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ccccc')"/></xsl:call-template></xsl:when>
<xsl:when test="contains($pText1, 'ddddd')">
<xsl:value-of select="substring-before($pText1,'ddddd')"/><xsl:text>Beta4</xsl:text>
<xsl:call-template name="tempFindReplace"><xsl:with-param name="pText1" select="substring-after($pText1, 'ddddd')"/></xsl:call-template></xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($pText1,1,1)"/>
<xsl:call-template name="tempFindReplace">
<xsl:with-param name="pText1" select="substring($pText1, 2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

Need help in grouping and transposing data using XSLT

I need help in conditional grouping and transposing XML data.
I need to group and transpose data using week of the month, Worker ID and Rate_Category_Code. Need to report the Hours_Worked in the appropriate weeks. Hours would be blank for all other week. Data in XML will be never for more then a month.
If there are overtime hours reported (Identified by Rate_Category_Code as OT) then i need to create separate row for the week in which overtime hours was reported.
Below is the XML data -
``
<?xml version="1.0" encoding="UTF-8"?>
<wd:Report_Data xmlns:wd="urn:com.workday.report/INT1120_CR_HR_Fieldglass_Daily_Timesheet">
<wd:Report_Entry>
<wd:Worker_ID>FNRAWK00001743</wd:Worker_ID>
<wd:Task_Code>01</wd:Task_Code>
<wd:GL_Account_Code>Default</wd:GL_Account_Code>
<wd:Rate_Category_Code>ST</wd:Rate_Category_Code>
<wd:UOM>HR</wd:UOM>
<wd:Hours_Worked>8</wd:Hours_Worked>
<wd:Reported_Date>2019-06-10</wd:Reported_Date>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:Worker_ID>FNRAWK00001743</wd:Worker_ID>
<wd:Task_Code>01</wd:Task_Code>
<wd:GL_Account_Code>Default</wd:GL_Account_Code>
<wd:Rate_Category_Code>ST</wd:Rate_Category_Code>
<wd:UOM>HR</wd:UOM>
<wd:Hours_Worked>8</wd:Hours_Worked>
<wd:Reported_Date>2019-06-18</wd:Reported_Date>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:Worker_ID>FNRAWK00001743</wd:Worker_ID>
<wd:Task_Code>01</wd:Task_Code>
<wd:GL_Account_Code>Default</wd:GL_Account_Code>
<wd:Rate_Category_Code>OT</wd:Rate_Category_Code>
<wd:UOM>HR</wd:UOM>
<wd:Hours_Worked>1</wd:Hours_Worked>
<wd:Reported_Date>2019-06-10</wd:Reported_Date>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:Worker_ID>FNRAWK00001742</wd:Worker_ID>
<wd:Task_Code>01</wd:Task_Code>
<wd:GL_Account_Code>Default</wd:GL_Account_Code>
<wd:Rate_Category_Code>ST</wd:Rate_Category_Code>
<wd:UOM>HR</wd:UOM>
<wd:Hours_Worked>9</wd:Hours_Worked>
<wd:Reported_Date>2019-06-20</wd:Reported_Date>
</wd:Report_Entry>
</wd:Report_Data>
``
Desired output -
``
Type=Upload Full Time Sheet with Revision
Transaction=True
Approval Required=True
Messaging Required=False
Language=English (United States)
Number Format=#,##9.99 (Example: 1,234,567.99)
Date Format=MM/DD/YYYY
Submit=FALSE
Buyer=FNRA
Supplier Review=False
Comments=
Worker_ID|Month_Start_Date|First_Monday|Cost_Center_Code|Task_Code|GL_Account_Code|Rate_Category_Code|UOM|Mon_Hrs|Tue_Hrs|Wed_Hrs|Thu_Hrs|Fri_Hrs|Sat_Hrs|Sun_Hrs
FNRAWK00001743|06/01/2019|05/27/2019||01|Default|ST|HR||||||||
FNRAWK00001743|06/01/2019|06/03/2019||01|Default|ST|HR||||||||
FNRAWK00001743|06/01/2019|06/10/2019||01|Default|ST|HR|8|||||||
FNRAWK00001743|06/01/2019|06/10/2019||01|Default|OT|HR|1|||||||
FNRAWK00001743|06/01/2019|06/17/2019||01|Default|ST|HR||8||||||
FNRAWK00001743|06/01/2019|06/24/2019||01|Default|ST|HR||||||||
FNRAWK00001742|06/01/2019|05/27/2019||01|Default|ST|HR||||||||
FNRAWK00001742|06/01/2019|06/03/2019||01|Default|ST|HR||||||||
FNRAWK00001742|06/01/2019|06/10/2019||01|Default|ST|HR||||||||
FNRAWK00001742|06/01/2019|06/10/2019||01|Default|OT|HR||||||||
FNRAWK00001742|06/01/2019|06/17/2019||01|Default|ST|HR||||9||||
FNRAWK00001742|06/01/2019|06/24/2019||01|Default|ST|HR||||||||
``
XSLT -
``
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wd="urn:com.workday.report/INT1120_CR_HR_Fieldglass_Daily_Timesheet" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:my="http://www.example.com/my" xmlns:functx="http://www.functx.com" exclude-result-prefixes="xs my functx">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>
<xsl:variable name="Linefeed" select="'
'"/>
<xsl:variable name="Delimiter" select=" '|' "/>
<xsl:function name="functx:repeat-string" as="xs:string">
<xsl:param name="stringToRepeat" as="xs:string?"/>
<xsl:param name="count" as="xs:integer"/>
<xsl:sequence select="string-join((for $i in 1 to $count return $stringToRepeat),'')"/>
</xsl:function>
<xsl:function name="functx:pad-integer-to-length" as="xs:string">
<xsl:param name="integerToPad" as="xs:anyAtomicType?"/>
<xsl:param name="length" as="xs:integer"/>
<xsl:sequence select="if ($length < string-length(string($integerToPad))) then error(xs:QName('functx:Integer_Longer_Than_Length')) else concat (functx:repeat-string('0',$length - string-length(string($integerToPad))),string($integerToPad))"/>
</xsl:function>
<xsl:function name="functx:date" as="xs:date">
<xsl:param name="year" as="xs:anyAtomicType"/>
<xsl:param name="month" as="xs:anyAtomicType"/>
<xsl:param name="day" as="xs:anyAtomicType"/>
<xsl:sequence select="xs:date(concat(functx:pad-integer-to-length(xs:integer($year),4),'-',functx:pad-integer-to-length(xs:integer($month),2),'-',functx:pad-integer-to-length(xs:integer($day),2)))"/>
</xsl:function>
<!--Function which accepts date as input and returns the date for first day of the month (Input Date)-->
<xsl:function name="functx:first-day-of-month" as="xs:date?">
<xsl:param name="date" as="xs:anyAtomicType?"/>
<xsl:sequence select="functx:date(year-from-date(xs:date($date)),month-from-date(xs:date($date)),1)"/>
</xsl:function>
<!--Function which accepts date as input and returns the date for first day of the week-->
<xsl:function name="my:thisMonday">
<xsl:param name="date"/>
<xsl:variable name="epoch" select="xs:date('0001-01-01')"/>
<xsl:variable name="dayNumber" select="fn:days-from-duration($date - $epoch)"/>
<xsl:variable name="dayOfWeek" select="$dayNumber mod 7"/>
<xsl:value-of select="$date - xs:dayTimeDuration(concat('P', $dayOfWeek, 'D' ))"/>
</xsl:function>
<xsl:template match="wd:Report_Data">
<File>
<Header>
<xsl:text>Type=Upload Full Time Sheet with Revision</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Transaction=True</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Approval Required=True</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Messaging Required=False</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Language=English (United States)</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Number Format=#,##9.99 (Example: 1,234,567.99)</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Date Format=MM/DD/YYYY</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Submit=FALSE</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Buyer=FNRA</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Supplier Review=False</xsl:text>
<xsl:value-of select="$Linefeed"/>
<xsl:text>Comments=</xsl:text>
<xsl:value-of select="$Linefeed"/>
</Header>
<xsl:value-of select="$Linefeed"/>
<Header>
<xsl:text>Worker_ID|Date|Week_Start_Date|Cost_Center_Code|Task_Code|GL_Account_Code|Rate_Category_Code|UOM|Mon_Hrs|Tue_Hrs|Wed_Hrs|Thu_Hrs|Fri_Hrs|Sat_Hrs|Sun_Hrs</xsl:text>
<xsl:value-of select="$Linefeed"/>
</Header>
<xsl:for-each select="wd:Report_Entry">
<xsl:call-template name="Write_Rows"/>
</xsl:for-each>
</File>
</xsl:template>
<xsl:template name="Write_Rows">
<Record>
<Worker_ID>
<xsl:value-of select="wd:Worker_ID"/>
</Worker_ID>
<xsl:value-of select="$Delimiter"/>
<Date>
<!--<xsl:value-of select="concat(substring(wd:Date,6, 2),'/',substring(wd:Date, 9, 2),'/',substring(wd:Date, 1, 4))"/>-->
<!--Pass date in YYYY-MM-DD format to custom function and format the return value to 'MM/DD/YYYY'-->
<xsl:variable name="StartDateOfMonth" select="string(functx:first-day-of-month(xs:date(concat(substring(wd:Reported_Date, 1, 4),'-', substring(wd:Reported_Date,6, 2),'-',substring(wd:Reported_Date, 9, 2)))))"/>
<xsl:value-of select="concat(substring($StartDateOfMonth,6,2),'/',substring($StartDateOfMonth,9,2),'/',substring($StartDateOfMonth,1,4))"/>
</Date>
<xsl:value-of select="$Delimiter"/>
<Week_Start_Date>
<!--<xsl:variable name="WeekStartDate" select="my:thisMonday(xs:date('2019-06-01'))"/>-->
<!--Format the return value to 'MM/DD/YYYY'-->
<xsl:variable name="WeekStartDate" select="my:thisMonday(xs:date(wd:Reported_Date))"/>
<xsl:value-of select="concat(substring($WeekStartDate,6,2),'/',substring($WeekStartDate,9,2),'/',substring($WeekStartDate,1,4))"/>
</Week_Start_Date>
<xsl:value-of select="$Delimiter"/>
<Cost_Center_Code>
<xsl:value-of select="wd:Cost_Center_Code"/>
</Cost_Center_Code>
<xsl:value-of select="$Delimiter"/>
<Task_Code>
<xsl:value-of select="wd:Task_Code"/>
</Task_Code>
<xsl:value-of select="$Delimiter"/>
<GL_Account_Code>
<xsl:value-of select="wd:GL_Account_Code"/>
</GL_Account_Code>
<xsl:value-of select="$Delimiter"/>
<Rate_Category_Code>
<xsl:value-of select="wd:Rate_Category_Code"/>
</Rate_Category_Code>
<xsl:value-of select="$Delimiter"/>
<UOM>
<xsl:value-of select="wd:UOM"/>
</UOM>
<xsl:value-of select="$Delimiter"/>
<Hours_Worked>
<xsl:value-of select="wd:Hours_Worked"/>
</Hours_Worked>
<xsl:value-of select="$Delimiter"/>
<Overtime>
<xsl:value-of select="wd:Overtime"/>
</Overtime>
<xsl:value-of select="$Linefeed"/>
</Record>
</xsl:template>
</xsl:stylesheet>
``
I think part of the task is grouping with a composite key e.g. in XSLT 3:
<xsl:for-each-group select="wd:Report_Entry" composite="yes" group-by="wd:Worker_ID, wd:Rate_Category_Code, my:thisMonday(xs:date(wd:Reported_Date))">
<xsl:value-of select="current-grouping-key(), sum(current-group()/wd:Hours_Worked)" separator="|"/>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
That gives the existing data:
FNRAWK00001743|ST|2019-06-10|8
FNRAWK00001743|ST|2019-06-17|8
FNRAWK00001743|OT|2019-06-10|1
FNRAWK00001742|ST|2019-06-17|9
You will need to add logic for outputting empty lines for weeks for which there is no data.

XML to CSV (Generation of New Date with input Date)

I have a requirement in which I have to generate new date(YYYYMMDD) from the date which is coming in the record(YYYYMMDD) and below is logic for New date creation:
1.If 'MM - 1' = 0, Then make MM -'12', and Year value as YearFromActualDate - 1
2.DD is always '01'
3.If 'MM - 1' != 0, Then MM in output will be 'MM - 1' and Year will remain the same
I have mentioned the Expected Output which will give idea of above mentioned logic.
Please advise.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output method="text" encoding="utf-8" />
<xsl:param name="delim" select="','" />
<xsl:param name="quote" select="'"'" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="$quote" />
<xsl:text>Name</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:text>Date</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:text>NewDate</xsl:text>
<xsl:value-of select="$quote" />
<xsl:value-of select="$break" />
<xsl:apply-templates select="ID/ED/E1" />
</xsl:template>
<xsl:template match="E1">
<xsl:value-of select="$quote" />
<xsl:value-of select="name"/>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:value-of select="date"/>
<xsl:value-of select="$quote" />
<xsl:value-of select="$delim" />
<xsl:value-of select="$quote" />
<xsl:variable name="newdate" select="'01'" />
<xsl:variable name="inMonth" select="substring(date,5,2)" />
<xsl:variable name="inputYear" select="substring(date,1,4)" />
<xsl:choose>
<xsl:when test = "$inMonth='01'">
<xsl:variable name="calculatedMonth" select="12"/>
<xsl:value-of select="concat(xs:integer($inputYear) - 1,$calculatedMonth,$newdate)" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="inMonthlength" select="string-length(xs:string(xs:integer($inMonth) - 1))" />
<xsl:if test="xs:integer($inMonthlength) !=2">
<xsl:value-of select="concat($inputYear,concat(0,xs:integer($inMonth) - 1),$newdate)" />
</xsl:if>
<xsl:if test="xs:integer($inMonthlength) =2">
<xsl:value-of select="concat($inputYear,(xs:integer($inMonth) - 1),$newdate)" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$quote"/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break" />
</xsl:if>
</xsl:template>
Input:
<ID>
<ED>
<E1>
<name>Eva</name>
<date>20190504</date> (Consider date as YYYYMMDD)
</E1>
<E1>
<name>Alan</name>
<date>20190101</date>
</E1>
</ED>
<ID>
Expected Output:
"Name","Date","NewDate"
"Eva","20190504","20190401"
"Alan","20190101","20181201"
If I've reverse-engineered your algorithm correctly, what you want is the first day of the previous month.
Logically the steps are:
Convert your date to an xs:date value
Take the first day of the current month
Subtract one month.
In practice it's simplest to combine (1) and (2) so you end up with
xs:date(replace($date, '(....)(..)(..)', '$1-$2-01')) - xs:yearMonthDuration('P1M')
and then you can format this date as YYYYMMDD using
format-date($date, '[Y0001][M01][D01]')

Roman Numeral to integer value using xslt

Is there any function to convert roman number to integer like format-number function can change integer number to roman number. As i am working on conversion a roman number to integer. if there is no function than i have to handle this in templates.
I have handle this through writing own function, but there is an issue that it is not validate the input value such as (VII or IVII is same) but output is correct.
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:number="http://dummy" version="2.0" >
<xsl:output method="text"/>
<xsl:template match="/">
(<xsl:value-of select="number:RomanToInteger('MMXVII', 0)"/>)
</xsl:template>
<xsl:function name="number:RomanToInteger">
<xsl:param name="romannumber"/>
<xsl:param name="followingvalue"/>
<xsl:choose>
<xsl:when test="ends-with($romannumber,'CM')">
<xsl:value-of select="900 + number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 900)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'M')">
<xsl:value-of select="1000+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 1000)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'CD')">
<xsl:value-of select="400+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 400)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'D')">
<xsl:value-of select="500+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 500)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'XC')">
<xsl:value-of select="90+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 90)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'C')">
<xsl:value-of select="(if(100 ge number($followingvalue)) then 100 else -100)+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 100)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'XL')">
<xsl:value-of select="40+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 40)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'L')">
<xsl:value-of select="50+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 50)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'IX')">
<xsl:value-of select="9+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 9)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'X')">
<xsl:value-of select="(if(10 ge number($followingvalue)) then 10 else -10) + number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 10)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'IV')">
<xsl:value-of select="4+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-2), 4)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'V')">
<xsl:value-of select="5+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 5)"/>
</xsl:when>
<xsl:when test="ends-with($romannumber,'I')">
<xsl:value-of select="(if(1 ge number($followingvalue)) then 1 else -1)+ number:RomanToInteger(substring($romannumber,1,string-length($romannumber)-1), 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>

Umbraco outputting filesize

I'm trying to output the correct size for pdf files that has been uploaded.
But the only output is 0 - what am I doing wrong?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:umbraco.contour="urn:umbraco.contour"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbraco.contour ">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:variable name="documentTypeAlias" select="string('PdfItem')"/>
<xsl:variable name="size" select="#currentpage/data [#alias = 'umbracoBytes']" />
<xsl:variable name="sizeAndSuffix">
<xsl:choose>
<xsl:when test="$size >= 1073741824">
<xsl:value-of select="format-number($size div 1073741824,'#,###')"/>
<xsl:text>GB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1048576">
<xsl:value-of select="format-number($size div 1048576,'#,###')"/>
<xsl:text>MB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1024">
<xsl:value-of select="format-number($size div 1024,'#,###')"/>
<xsl:text>KB</xsl:text>
</xsl:when>
<xsl:when test="$size > 0 and $size < 1024">
<xsl:value-of select="format-number($size div 0,'#,###')"/>
<xsl:text> Bytes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>0 Bytes</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="$currentPage/node [#nodeTypeAlias = $documentTypeAlias and string(data [#alias='umbracoNaviHide']) != '0']">
<div class="pdf">
<a>
<xsl:attribute name="class">pdfmenu</xsl:attribute>
<xsl:attribute name="href"><xsl:value-of select="umbraco.library:GetMedia(./data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']"/></xsl:attribute>
<strong><xsl:value-of select="#nodeName"/><span>
(<xsl:value-of select="$sizeAndSuffix"/>)</span></strong>
<em><xsl:value-of select="data [#alias = 'PDFBeskrivelse']"/></em>
<img>
<xsl:attribute name="src"><xsl:value-of select="data [#alias = 'PDFBillede']"/></xsl:attribute>
<xsl:attribute name="alt"></xsl:attribute>
<xsl:attribute name="height">200</xsl:attribute>
<xsl:attribute name="width">141</xsl:attribute>
</img>
</a>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Alright, I've move the size variable into the for-each loop, as it varies per file and fixed a few typos:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:umbraco.contour="urn:umbraco.contour"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbraco.contour ">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:variable name="documentTypeAlias" select="string('PdfItem')"/>
<xsl:template match="/">
<xsl:for-each select="$currentPage/node [#nodeTypeAlias = $documentTypeAlias and string(data [#alias='umbracoNaviHide']) != '0']">
<xsl:if test="string(data [#alias = 'pdf']) != ''">
<xsl:variable name="size" select="umbraco.library:GetMedia(data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']" />
<xsl:variable name="sizeAndSuffix">
<xsl:choose>
<xsl:when test="$size >= 1073741824">
<xsl:value-of select="format-number($size div 1073741824,'#,###')"/>
<xsl:text>GB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1048576">
<xsl:value-of select="format-number($size div 1048576,'#,###')"/>
<xsl:text>MB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1024">
<xsl:value-of select="format-number($size div 1024,'#,###')"/>
<xsl:text>KB</xsl:text>
</xsl:when>
<xsl:when test="$size > 0 and $size < 1024">
<xsl:value-of select="format-number($size div 0,'#,###')"/>
<xsl:text> Bytes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>0 Bytes</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="pdf">
<a>
<xsl:attribute name="class">pdfmenu</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="umbraco.library:GetMedia(data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']"/>
</xsl:attribute>
<strong>
<xsl:value-of select="#nodeName"/>
<span>
(<xsl:value-of select="$sizeAndSuffix"/>)
</span>
</strong>
<em>
<xsl:value-of select="data [#alias = 'PDFBeskrivelse']"/>
</em>
<img>
<xsl:attribute name="src">
<xsl:value-of select="data [#alias = 'PDFBillede']"/>
</xsl:attribute>
<xsl:attribute name="alt"></xsl:attribute>
<xsl:attribute name="height">200</xsl:attribute>
<xsl:attribute name="width">141</xsl:attribute>
</img>
</a>
</div>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
That should do the trick.

Resources