Start question numbering at 47 instead of 00 - xslt-2.0

How do I get the questions to number starting at 47 and not 00. I need the first number to be mc15q6647. This script below is giving me mc15q6601.
<xsl:when test="count(preceding::xhtml:li[#property = 'ktp:question']) + 1 < 50">
mc15q6647
<xsl:value-of select="format-number(count(preceding::xhtml:li[#property = 'ktp:question']) + 1, '00')" />
</xsl:when>

Related

how can I Create a list variable from other lists in a condition

I have a list requiredStyles that is composed of other list depending on a series variable.
but it's not working correctly I get the output:
Warning: will not be created contain a cell paragraph with Adiv Adiv2 ADiv3 AC1 C1 fld-c1 ACount AJur
It doesn't seem to be creating requiredStyles as a list. Please assist.
requiredStyles
<xsl:variable name="requiredStyles">
<xsl:choose>
<xsl:when test="$series = 'Alpha'">
<xsl:value-of select=" ( $styleList1 , $styleList2 , $styleList3 , $styleList4 ) "/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=" ( $styleList1 , $styleList2 , $styleList3 ) "/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test=" string-join( w:tr[ w:tc[1]/w:p[ w:pPr/w:pStyle[ #w:val = ( $requiredStyles ) ] ] ]/w:tc[2]//w:t , '' ) = '' ">
<xsl:call-template name="outputErrorMessage">
<xsl:with-param name="messageText" as="xs:string">
<xsl:variable name="temp" as="xs:string+">
<xsl:text>Warning: will not be created contain a cell paragraph with "</xsl:text>
<xsl:value-of select=" ( $requiredStyles ) " separator='", or "'/>
<xsl:text>" style.</xsl:text>
</xsl:variable>
<xsl:sequence select=" string-join( $temp , '' ) "/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
...
</xsl:otherwise>
Moving it to and xpath if did the trick
Fiddle solution
<xsl:variable name="requiredStyles2" as="xs:string+"
select="
if ($series = 'Alpha')
then
( $style1 , $style2 , $style3 , $style4 )
else
( $style1 , $style2 , $style4 )
"
/>

Group and Count data

I am working on trying to compute counts for each student assessment based on different steps in the review of test. Student test evaluation has multiple levels Application Evaluation, Written Test, Group Interview, Interview. I have find counts based on gender at each level.
xml:
<xd:StudentData xmlns:xd="urn:com.student.report/student_test">
<xd:StudentRecord>
<xd:StudentRequisition xd:Descriptor="1858 Economics"></xd:StudentRequisition>
<xd:StudentStatus xd:Descriptor="Pass"></xd:StudentStatus>
<xd:StudentApplication xd:Descriptor="1858 Economics"></xd:StudentApplication>
<xd:StudentID>S-1</xd:StudentID>
<xd:Gender xd:Descriptor="Male"></xd:Gender>
<xd:StudentDate>2020-01-01-12:00</xd:StudentDate>
<xd:Total_Score>75</xd:Total_Score>
<xd:ProfileStudentTestGroup>
<xd:StudentTest xd:Descriptor="Student Evaluation"></xd:StudentTest>
<xd:StudentTest_Status xd:Descriptor="Pass"></xd:StudentTest_Status>
<xd:StudentTest_Date>2020-01-31-12:00</xd:StudentTest_Date>
<xd:StudentTest_Result_Score>75</xd:StudentTest_Result_Score>
</xd:ProfileStudentTestGroup>
</xd:StudentRecord>
<xd:StudentRecord>
<xd:StudentRequisition xd:Descriptor="1500 Social Service"></xd:StudentRequisition>
<xd:StudentStatus xd:Descriptor="Fail"></xd:StudentStatus>
<xd:StudentApplication xd:Descriptor="1500 Social Service"></xd:StudentApplication>
<xd:StudentID>S-3</xd:StudentID>
<xd:Gender xd:Descriptor="Female"></xd:Gender>
<xd:StudentDate>2020-01-01-12:00</xd:StudentDate>
<xd:Total_Score>65</xd:Total_Score>
<xd:ProfileStudentTestGroup>
<xd:StudentTest xd:Descriptor="Student Evaluation"></xd:StudentTest>
<xd:StudentTest_Status xd:Descriptor="Pass"></xd:StudentTest_Status>
<xd:StudentTest_Date>2020-01-31-12:00</xd:StudentTest_Date>
<xd:StudentTest_Result_Score>65</xd:StudentTest_Result_Score>
</xd:ProfileStudentTestGroup>
</xd:StudentRecord>
<xd:StudentRecord>
<xd:StudentRequisition xd:Descriptor="1500 Social Service"></xd:StudentRequisition>
<xd:StudentStatus xd:Descriptor="Fail"></xd:StudentStatus>
<xd:StudentApplication xd:Descriptor="1500 Social Service"></xd:StudentApplication>
<xd:StudentID>S-4</xd:StudentID>
<xd:Gender xd:Descriptor="Female"></xd:Gender>
<xd:StudentDate>2020-01-01-12:00</xd:StudentDate>
<xd:Total_Score>67</xd:Total_Score>
<xd:ProfileStudentTestGroup>
<xd:StudentTest xd:Descriptor="Student Evaluation"></xd:StudentTest>
<xd:StudentTest_Status xd:Descriptor="Pass"></xd:StudentTest_Status>
<xd:StudentTest_Date>2020-01-31-12:00</xd:StudentTest_Date>
<xd:StudentTest_Result_Score>67</xd:StudentTest_Result_Score>
</xd:ProfileStudentTestGroup>
</xd:StudentRecord>
<xd:StudentRecord>
<xd:StudentRequisition xd:Descriptor="1858 Economics"></xd:StudentRequisition>
<xd:StudentStatus xd:Descriptor="Pass"></xd:StudentStatus>
<xd:StudentApplication xd:Descriptor="1858 Economics"></xd:StudentApplication>
<xd:StudentID>S-7</xd:StudentID>
<xd:Gender xd:Descriptor="Male"></xd:Gender>
<xd:StudentDate>2020-01-01-12:00</xd:StudentDate>
<xd:Total_Score>85</xd:Total_Score>
<xd:ProfileStudentTestGroup>
<xd:StudentTest xd:Descriptor="Student Evaluation"></xd:StudentTest>
<xd:StudentTest_Status xd:Descriptor="Pass"></xd:StudentTest_Status>
<xd:StudentTest_Date>2020-01-31-12:00</xd:StudentTest_Date>
<xd:StudentTest_Result_Score>85</xd:StudentTest_Result_Score>
</xd:ProfileStudentTestGroup>
</xd:StudentRecord>
</xd:StudentData>
xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xd="urn:com.student.report/student_test">
<xsl:iterate select="StudentData/StudentRecord">
<xsl:param name="male_pass_count" select="0.00" as="xs:integer"/>
<xsl:param name="male_fail_count" select="0.00" as="xs:integer"/>
<xsl:param name="female_pass_count" select="0.00" as="xs:integer"/>
<xsl:param name="female_fail_count" select="0.00" as="xs:integer"/>
<xsl:param name="StudentTest" select="{/xd:StudentTest/#xd:Descriptor}" as="xs:string"/>
<xsl:choose>
<xsl:when test="{/xd:Gender/#xd:Descriptor} = 'Male'">
<xsl:if test="{/xd:StudentTest_status/#xd:Descriptor} = 'Pass'">
<xsl:with-param name="male_pass_count" select="$male_pass_count + 1"/>
</xsl:if>
<xsl:if test="{/xd:StudentTest_status/#xd:Descriptor} = 'Fail'">
<xsl:with-param name="male_fail_count" select="$male_fail_count + 1"/>
</xsl:if>
</xsl:when>
<xsl:when test="{/xd:Gender/#xd:Descriptor} = 'Female'">
<xsl:if test="{/xd:StudentTest_status/#xd:Descriptor} = 'Pass'">
<xsl:with-param name="female_pass_count" select="$female_pass_count + 1"/>
</xsl:if>
<xsl:if test="{/xd:StudentTest_status/#xd:Descriptor} = 'Fail'">
<xsl:with-param name="female_fail_count" select="$female_fail_count + 1"/>
</xsl:if>
</xsl:when>
</xsl:choose>
<xsl:on-completion>
<student id="{$StudentTest}">
<male_pass_count>{$male_pass_count}</male_pass_count>
<male_fail_count>{$male_fail_count}</male_fail_count>
<female_pass_count>{$female_pass_count}</female_pass_count>
<female_fail_count>{$female_fail_count}</female_fail_count>
</student>
</xsl:on-completion>
</xsl:iterate>
output:
StudentRequisition StudentTest MalePass MaleFail FemalePass FemaleFail
1858 Economics Application evaluation 22 0 10 0
1858 Economics Interview 6 11 0 5
1858 Economics Written Test 2 0 2 0
1500 Social Service Application evaluation 10 12 10 12
1500 Social Service Interview 0 0 0 0
1500 Social Service Written Test 0 0 0 0
If you use an XSLT 3 processor (as your use it xsl:iterate indicates) you can use for-each-group with a composite grouping key on the requisition and the test I think:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="urn:com.student.report/student_test"
xmlns:xd="urn:com.student.report/student_test"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output indent="yes" method="html" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>Grouping example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="StudentData">
<table>
<thead>
<tr>
<th>Student Requisition</th>
<th>Student Test</th>
<th>Male Pass</th>
<th>Male Fail</th>
<th>Female Pass</th>
<th>Female Fail</th>
</tr>
</thead>
<tbody>
<xsl:for-each-group select="StudentRecord" composite="yes" group-by="StudentRequisition/#xd:Descriptor, ProfileStudentTestGroup/StudentTest/#xd:Descriptor">
<tr>
<td>{current-grouping-key()[1]}</td>
<td>{current-grouping-key()[2]}</td>
<td>{count(current-group()[Gender/#xd:Descriptor = 'Male'][ProfileStudentTestGroup/StudentTest_Status[#xd:Descriptor = 'Pass']])}</td>
<td>{count(current-group()[Gender/#xd:Descriptor = 'Male'][ProfileStudentTestGroup/StudentTest_Status[#xd:Descriptor = 'Fail']])}</td>
<td>{count(current-group()[Gender/#xd:Descriptor = 'Female'][ProfileStudentTestGroup/StudentTest_Status[#xd:Descriptor = 'Pass']])}</td>
<td>{count(current-group()[Gender/#xd:Descriptor = 'Female'][ProfileStudentTestGroup/StudentTest_Status[#xd:Descriptor = 'Fail']])}</td>
</tr>
</xsl:for-each-group>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/93dFepD
If you use an XSLT 2 processor (which doesn't support a composite grouping key) then either concat the two values or nest two for-each-group instructions.

XML to Fixed Length File Using XSLT_Complex Position Logic- PART 2

We have a requirement in which need to convert XML into Fixed Length File. First record is as header and after that we have actual records..From 2 record onwards we need to apply the logic which is mentioned below:
After length 45, consider 10 numbers 0000001000, what ever be the last digit we need to check and replace by following the below table.
Same logic we need to repeat at position 59th to 74th.
77th to 80th we need to get the value 5152 and store into one variable
I had asked the question with 1st logic and got the awesome response, now I am left with 2nd and 3rd logic
For Positive: (0000001000) - (000000100{)
{= 0
A = 1
B = 2
c = 3
D = 4
E = 5
F = 6
G = 7
H = 8
I = 9
Request anyone to help me to achieve the same, I have mentioned the XSLT which I got from previous answers.Thanks
Input:
<ZR>
<INPUT>
<I_FIL>ERES</I_FIL>
</INPUT>
<TABLES>
<T_ER>
<item>
<DATA> HEADER1111111122222222333333344456</DATA>
</item>
<item>
<DATA>778944 D4E2 EA 1234567891 2018-11-060000001000EA 0000000000000100005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05</DATA>
</item>
<item>
<DATA>987654 D4E2 EA 1987654321 2018-11-060000002001EA 0000000000000100005152D04YA30UUU0000000XXXLRB 100{ Q 2018-11-05</DATA>
</item>
.
.
.
.
.
.
.
.
<item>
<DATA>12345678912345678934562754378909726533297TRAILER</DATA>
</item>
</T_ER>
</TABLES>
</ZR>
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
<xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
<xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1),
10)"/>
<xsl:variable name="charToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9), $charToReplace, substring(DATA,($length+11),(string-length(DATA) + 1)))"/>
<xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
OR
<xsl:template match="/">
<xsl:value-of select="
ZR/TABLES/T_ER/item[1]/DATA,
ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(
substring(., 1, 54),
substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1),
substring(., 56)
)" separator="
" />
</xsl:template>
Expected Output:
HEADER1111111122222222333333344456
778944 D4E2 EA 1234567891 2018-11-06000000100{EA
000000000000010{005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05
987654 D4E2 EA 1987654321 2018-11-06000000200AEA
000000000000010{005152D04YA30UUU0000000XXXLRB 100{ Q 2018-11-05
.
.
.
.
12345678912345678934562754378909726533297TRAILER
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
<xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
<xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 10)" />
<xsl:variable name="sixteenNumbers" select="substring(DATA, (string-length(substring(DATA,0,59)) + 1), 16)" />
<xsl:variable name="firstCharToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:variable name="secondCharToReplace" select="translate(substring($sixteenNumbers, string-length($sixteenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:choose>
<xsl:when test="string-length($tenNumbers) != 10">
<xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring(DATA,0,46),
substring(DATA, ($length + 1), 9),
$firstCharToReplace,
substring(DATA,($length+11), 18),
$secondCharToReplace,
substring(DATA,($length+30),(string-length(DATA) + 1)))" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$break" />
<xsl:variable name="temp" select="substring(DATA,77,4)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
It depends on what condition you want to replace the char.
If it is based on after EA (as per comment) the solution would be different.
For now, I have implemented it solely length based with both points 2 & 3 covered.
http://xsltfiddle.liberty-development.net/6r5Gh38/1
EDIT:
http://xsltfiddle.liberty-development.net/6r5Gh38/2
EDIT 2:
Brief about the points mentioned in comment:
1. <xsl:when test="string-length($tenNumbers) != 10"> This condition is added to remove that extra R appearing for last <item> .
It means if the 10 numbers we are taking in variable is actually having 10 numbers or not.
In the last case,
<item>
<DATA>12345678912345678934562754378909726533297TRAILER</DATA>
</item>
We don't get 10 numbers after 46th character. We get less than that. That's the reason the output has been separated out for two different cases.
2. substring(DATA,0,46) --> which will take first 45 characters to match 778944 D4E2 EA 1234567891 2018-11-06
substring(DATA, ($length + 1), 9) --> which will take 9 characters from index 46th to match 000000100
$firstCharToReplace --> This will replace 10th character as your requirement of 1st question i.e. {
substring(DATA,($length+11), 18) --> It will start remaining string from index (45+11)th to 18 characters that matches EA 000000000000010
$secondCharToReplace --> This will replace (45+11+18)= 74th character as your requirement of 2nd question i.e. {
substring(DATA,($length+30),(string-length(DATA) + 1)) --> It starts from (45+30)= 75th character to last index and gives 005152D04YA30TRE0000000XXXYYY 800{ Q 2018-11-05
Note: In your case, there are extra tabs and white-spaces exist in between the string. That's why the index number has been changed to match your expected output.

Add space between nodes in XSLT

XML file :
<string-name>
<surname>Husebo</surname><given-names>BS</given-names>
</string-name>, <string-name>
<surname>Ballard</surname> <given-names>C</given-names></string-name>
XSL :
<xsl:template match="surname">
<xsl:choose>
<xsl:when test = "following-sibling::node()[not(./*) and normalize-space(.)='']">
<xsl:text> </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
output : Husebo BS, Ballard C
I want to add a space between < surname> and < given-name> tag after checking a blank space. ex - For first < string-name> there is no space between < surname> and < given-name> so after checking that after < /surname> a blankspace should be added. but in the 2nd < /string-name> tag there a blankspace is already exists so no space will be added there. please help !!!
Use this code hope it will help you:
<xsl:template match="surname[not(following-sibling::node()[1][self::text()[. = ' ']])]">
<xsl:apply-templates/>
<xsl:text> </xsl:text>
</xsl:template>
And if you want to make more specific then check that immediate following-sibling is given-name then use this code:
<xsl:template match="surname[not(following-sibling::node()[1][self::text()[. = ' ']]) and following-sibling::node()[1][self::given-names]]">
<xsl:apply-templates/>
<xsl:text> </xsl:text>
</xsl:template>
As long as given-names is not optional, you can check if the next text node is the same as the next node:
<xsl:template match="surname">
<xsl:choose>
<xsl:when test="following-sibling::node()[1] != following-sibling::text()[1]">
<xsl:apply-templates/>
<xsl:text> </xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Saxon XSLT2.0 Extracting Numbers from the String

I am trying to Extract Integer from a String using Xslt2.0
For Example consider the string "designa80000dd5424d" and i need the two integers inside the string i.e "8000" and "5424"
I tried using translate function as below
select="translate($term,translate($term, '0123456789', ''), '')"
But it combines both the integers and gives the output as "80005424"
i need something which separates them
I tried using translate function as below
select="translate($term,translate($term, '0123456789', ''), '')"
But it combines both the numbers and gives the output as "80005424" i
need something which separates them
I. Here is a complete XSLT 1.0 solution:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:variable name="vSpaces">
<xsl:call-template name="makeSpaces"/>
</xsl:variable>
<xsl:variable name="vtheNumbers"
select="normalize-space(translate(., translate(.,'0123456789',''), $vSpaces))"/>
<xsl:call-template name="tokenize">
<xsl:with-param name="pStr" select="$vtheNumbers"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="pStr"/>
<xsl:param name="pInd" select="1"/>
<xsl:if test="string-length($pStr)">
<xsl:value-of select=
"concat($pInd, ': ',substring-before(concat($pStr, ' '), ' '), '
')"/>
<xsl:call-template name="tokenize">
<xsl:with-param name="pStr" select="substring-after($pStr, ' ')"/>
<xsl:with-param name="pInd" select="$pInd +1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="makeSpaces">
<xsl:param name="pLen" select="string-length(.)"/>
<xsl:choose>
<xsl:when test="$pLen = 1">
<xsl:value-of select="' '"/>
</xsl:when>
<xsl:when test="$pLen > 1">
<xsl:variable name="vHalfLen" select="floor($pLen div 2)"/>
<xsl:call-template name="makeSpaces">
<xsl:with-param name="pLen" select="$vHalfLen"/>
</xsl:call-template>
<xsl:call-template name="makeSpaces">
<xsl:with-param name="pLen" select="$pLen -$vHalfLen"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>designa80000dd5424dan1733g122</t>
the wanted, correct result is produced:
1: 80000
2: 5424
3: 1733
4: 122
Do note:
The last argument of the outer translate() is a string having the same number of characters as that of the input string, and each of these characters is a space.
II. XPath 2.0 shorter and simpler
This XPath 2.0 expression when evaluated produces the wanted sequence of numbers:
tokenize(., '[^\d]+')[.]
Here is an XSLT - based verification:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="vNumbers"
select="tokenize(., '[^\d]+')[.]"/>
<xsl:for-each select="$vNumbers">
<xsl:value-of select="concat(position(), ': ', ., '
')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the same XML document:
<t>designa80000dd5424dan1733g122</t>
the same correct result is produced:
1: 80000
2: 5424
3: 1733
4: 122
You could try it using tokenize with any non-digit sequences as the separator, i.e. using XPath 3.0 tokenize('designa80000dd5424d', '[^0-9]+')[normalize-space()]!number() or in XSLT/XPath 2.0 as for $t in tokenize('designa80000dd5424d', '[^0-9]+')[normalize-space()] return number($t) or you could use xsl:analyze-string (XSLT 2.0) or the analyze-string function (XSLT/XPath 3.0, but available with Saxon 9.7 HE).

Resources