I am trying to make xslt script which display result in tabular format but I am getting result column value added in next row. please check image below for expected output.
Input xml file:
<?xml version="1.0"?>
<Softwares>
<SubNodes>
<Software>
<Results>
<Info>
<Name>Visual Studio</Name>
<Key>Name</Key>
<Value>2010</Value>
</Info>
<Info>
<Name>Visual Studio</Name>
<Key>Driver ID</Key>
<Value>DI8745</Value>
</Info>
</Results>
</Software>
<Software>
<Results>
<Info>
<Name>Oracle</Name>
<Key>Name</Key>
<Value>Oracle8</Value>
</Info>
<Info>
<Name>Oracle</Name>
<Key>Driver ID</Key>
<Value>ID2345</Value>
</Info>
</Results>
</Software>
<Software>
<Results>
<Info>
<Name>SQL</Name>
<Key>Name</Key>
<Value>SQL2005</Value>
</Info>
<Info>
<Name>SQL</Name>
<Key>Driver ID</Key>
<Value>ID8888</Value>
</Info>
</Results>
</Software>
</SubNodes>
</Softwares>
XSLT file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w3="http://www.w3.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<table>
<tr>
<td>Name</td>
<td>Driver ID</td>
</tr>
<xsl:for-each select="//SubNodes/Software/Results/Info">
<tr>
<td>
<xsl:choose>
<xsl:when test="Key = 'Name'">
<xsl:value-of select="Value" />
</xsl:when>
</xsl:choose>
</td>
<td>
<xsl:choose>
<xsl:when test="Key = 'Driver ID'">
<xsl:value-of select="Value" />
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Current Output:
Image shows current output which is not giving result in row by row.
Expected output
Image shows expected output which is giving result in row by row.
Your XSLT will output a row for every Info. Try this instead:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w3="http://www.w3.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<table>
<tr>
<td>Name</td>
<td>Driver ID</td>
</tr>
<xsl:for-each select="//SubNodes/Software/Results">
<tr>
<td>
<xsl:choose>
<xsl:when test="Info[1]/Key = 'Name'">
<xsl:value-of select="Info[1]/Value" />
</xsl:when>
</xsl:choose>
</td>
<td>
<xsl:choose>
<xsl:when test="Info[2]/Key = 'Driver ID'">
<xsl:value-of select="Info[2]/Value" />
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Related
i got the following XML Data and need to create 2 Tables looking like this with only xsl 1.0
Ribbon Rezept
Medikament
Dosis
08:00
12:00
18:00
22:00
ASPIRIN
0-0-0-1
0
0
0
1
Ribbon Medikarte
Medikament
Dosis
08:00
12:00
16:00
20:00
22:00
ASPIRIN
0-0-0-1
0
0
0
1
PONSTAN
1-0-0-1
1
0
0
1
But the result with the below xsl ist not creating the expected tables
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl"?>
<DATA>
<RIBBON_REZEPT>
<SRO_INT_REZEPT_INFO>
<MRO_INT_REZEPT>
<MEDIKAMENT_M CR="1">ASPIRIN</MEDIKAMENT_M>
<DOSIS_M CR="1">0-0-0-1</DOSIS_M>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>08:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>12:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>18:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>1</DOSIS_N>
<ZEIT_T>22:00</ZEIT_T>
</EINZELDOSIS>
<EINHEIT_M CR="1">Stk</EINHEIT_M>
</MRO_INT_REZEPT>
</SRO_INT_REZEPT_INFO>
</RIBBON_REZEPT>
<RIBBON_MEDIKARTE>
<SRO_INT_REZEPT_INFO>
<MRO_INT_REZEPT>
<MEDIKAMENT_M CR="1">ASPIRIN</MEDIKAMENT_M>
<DOSIS_M CR="1">0-0-0-1</DOSIS_M>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>08:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>12:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>16:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>1</DOSIS_N>
<ZEIT_T>20:00</ZEIT_T>
</EINZELDOSIS>
<EINHEIT_M CR="1">Stk</EINHEIT_M>
</MRO_INT_REZEPT>
<MRO_INT_REZEPT>
<MEDIKAMENT_M CR="1">PONSTAN</MEDIKAMENT_M>
<DOSIS_M CR="1">1-0-0-1</DOSIS_M>
<EINZELDOSIS>
<DOSIS_N>1</DOSIS_N>
<ZEIT_T>08:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>12:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>0</DOSIS_N>
<ZEIT_T>16:00</ZEIT_T>
</EINZELDOSIS>
<EINZELDOSIS>
<DOSIS_N>1</DOSIS_N>
<ZEIT_T>22:00</ZEIT_T>
</EINZELDOSIS>
<EINHEIT_M CR="1">Stk</EINHEIT_M>
</MRO_INT_REZEPT>
</SRO_INT_REZEPT_INFO>
</RIBBON_MEDIKARTE>
</DATA>
From this Post i got a Solution, but as the Times are different within the Sub-Nodes (Ribbon Rezept and Medikarte), it does not work as expected :(
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://exslt.org/common" version="1.0">
<xsl:output encoding="ISO-8859-1" indent="yes" method="html"/>
<xsl:key match="EINZELDOSIS" name="data-by-time" use="ZEIT_T"/>
<xsl:key match="EINZELDOSIS" name="data-by-cell" use="concat(ZEIT_T, '|', generate-id(..))"/>
<xsl:template match="/">
<html>
<head charset="ISO-8859-1">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Medilist v2</title>
</head>
<body>
<p>Ribbon Rezept</p>
<xsl:call-template name="RIBBON">
<xsl:with-param name="medinode" select="/DATA/RIBBON_REZEPT/SRO_INT_REZEPT_INFO"/>
</xsl:call-template>
<p>Ribbon Medikarte</p>
<xsl:call-template name="RIBBON">
<xsl:with-param name="medinode" select="/DATA/RIBBON_MEDIKARTE/SRO_INT_REZEPT_INFO"/>
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="RIBBON">
<xsl:param name="medinode" />
<xsl:variable name="distinct-times-RTF">
<xsl:for-each select="$medinode/MRO_INT_REZEPT/EINZELDOSIS[count(. | key('data-by-time', ZEIT_T)[1]) = 1]">
<xsl:sort data-type="text" order="ascending" select="ZEIT_T"/>
<xsl:copy-of select="ZEIT_T"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="distinct-times" select="ext:node-set($distinct-times-RTF)/ZEIT_T"/>
<xsl:variable name="source_document" select="/"/>
<table border="1">
<thead>
<tr>
<th>Medi</th>
<th>Dosis</th>
<!-- a column header for each distinct time point -->
<xsl:for-each select="$distinct-times">
<th>
<xsl:value-of select="."/>
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="$medinode/MRO_INT_REZEPT">
<xsl:variable name="row-id" select="generate-id()"/>
<tr>
<td>
<xsl:value-of select="MEDIKAMENT_M"/>
</td>
<td>
<xsl:value-of select="DOSIS_M"/>
</td>
<!-- create a cell for each distinct time point
-->
<xsl:for-each select="$distinct-times">
<xsl:variable name="zeit" select="."/>
<td>
<!-- get matching data point -->
<!-- switch the context back to the source document -->
<xsl:for-each select="$source_document">
<xsl:value-of select="key('data-by-cell', concat($zeit, '|', $row-id))/DOSIS_N"/>
</xsl:for-each>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
i've put it as an example here on fiddle
Your XML has two branches - RIBBON_REZEPT and RIBBON_MEDIKARTE - with identical structure, apart from the name. In order to limit the first key to the current branch, you need to add the ID or the name of the branch to its value.
Instead of:
<xsl:key match="EINZELDOSIS" name="data-by-time" use="ZEIT_T"/>
define the key as:
<xsl:key match="EINZELDOSIS" name="data-by-time" use="concat(ZEIT_T, '|', name(../../..))" />
then call it as:
key('data-by-time', concat(ZEIT_T, '|', name($branch))
where $branch is either RIBBON_REZEPT or RIBBON_MEDIKARTE.
The other key is already limited to the current MRO_INT_REZEPT, so it can stay as it is.
With some streamlining, your stylesheet could look like this:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="html"/>
<xsl:key name="data-by-time" match="EINZELDOSIS" use="concat(ZEIT_T, '|', name(../../..))" />
<xsl:key name="data-by-cell" match="EINZELDOSIS" use="concat(ZEIT_T, '|', generate-id(..))" />
<xsl:variable name="source_document" select="/" />
<xsl:template match="/DATA">
<html>
<body>
<p>Ribbon Rezept</p>
<xsl:call-template name="create-table">
<xsl:with-param name="branch" select="RIBBON_REZEPT"/>
</xsl:call-template>
<p>Ribbon Medikarte</p>
<xsl:call-template name="create-table">
<xsl:with-param name="branch" select="RIBBON_MEDIKARTE"/>
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="create-table">
<xsl:param name="branch"/>
<xsl:variable name="recepts" select="$branch/SRO_INT_REZEPT_INFO/MRO_INT_REZEPT"/>
<xsl:variable name="doses" select="$recepts/EINZELDOSIS"/>
<!-- distinct times -->
<xsl:variable name="distinct-times-RTF">
<xsl:for-each select="$doses[count(. | key('data-by-time', concat(ZEIT_T, '|', name($branch)))[1]) = 1]">
<xsl:sort select="ZEIT_T" data-type="text" order="ascending"/>
<xsl:copy-of select="ZEIT_T"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="distinct-times" select="exsl:node-set($distinct-times-RTF)/ZEIT_T" />
<!-- table -->
<table border="1">
<thead>
<tr>
<th>Medikament</th>
<th>Dosis</th>
<!-- a column header for each distinct time -->
<xsl:for-each select="$distinct-times">
<th>
<xsl:value-of select="."/>
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="$recepts">
<xsl:variable name="recept-id" select="generate-id()" />
<tr>
<td>
<xsl:value-of select="MEDIKAMENT_M"/>
</td>
<td>
<xsl:value-of select="DOSIS_M"/>
</td>
<!-- create a cell for each distinct time -->
<xsl:for-each select="$distinct-times">
<xsl:variable name="time" select="." />
<td>
<!-- switch the context back to the source document -->
<xsl:for-each select="$source_document">
<!-- get data from the intersection of column (time) and row (recept) -->
<xsl:value-of select="key('data-by-cell', concat($time, '|', $recept-id))/DOSIS_N" />
</xsl:for-each>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
Here is a snippet of XML:
<?xml version="1.0" encoding="utf-8"?>
<AssignmentHistory Version="171804">
<W20160229>
<ReviewQuestion>Why will God’s Kingdom have to crush the earthly rulerships depicted in the image? (Da 2:44)</ReviewQuestion>
<StudentItems>
<Item>
<Name Counsel="9" NextCounsel="0" Completed="1">Finlay Truckle</Name>
<Type>Bible Reading (Main)</Type>
<Description>Bible Reading</Description>
</Item>
<Item>
<Name Counsel="38" NextCounsel="0" Completed="1">Name</Name>
<Type>#1 Student (Main)</Type>
<Description>Initial Call</Description>
</Item>
<Item>
<Name>Name</Name>
<Type>Assistant</Type>
<Description>Initial Call</Description>
</Item>
<Item>
<Name Counsel="41" NextCounsel="0" Completed="1">Name</Name>
<Type>#2 Student (Main)</Type>
<Description>Return Visit</Description>
</Item>
<Item>
<Name>¬DELETED¬</Name>
<Type>Assistant</Type>
<Description>Return Visit</Description>
</Item>
<Item>
<Name Counsel="45" NextCounsel="0" Completed="1">Name</Name>
<Type>#3 Student (Main)</Type>
<Description>Bible Study</Description>
</Item>
<Item>
<Name>Name</Name>
<Type>Assistant</Type>
<Description>Bible Study</Description>
</Item>
</StudentItems>
</W20160229>
<W20160404/>
<W20160411>
<ReviewQuestion>What did the immense tree in Nebuchadnezzar’s dream represent? (Da 4:10, 11, 20-22)</ReviewQuestion>
<StudentItems>
<Item>
<Name Counsel="11" NextCounsel="0" Completed="1">Name</Name>
<Type>Bible Reading (Main)</Type>
<Description>Bible Reading</Description>
</Item>
<Item>
<Name Counsel="0" NextCounsel="0" Completed="1">Name</Name>
<Type>#1 Student (Main)</Type>
<Description>Initial Call</Description>
</Item>
<Item>
<Name>Name</Name>
<Type>Assistant</Type>
<Description>Initial Call</Description>
</Item>
<Item>
<Name Counsel="37" NextCounsel="0" Completed="1">Name</Name>
<Type>#2 Student (Main)</Type>
<Description>Return Visit</Description>
</Item>
<Item>
<Name>Name</Name>
<Type>Assistant</Type>
<Description>Return Visit</Description>
</Item>
<Item>
<Name Counsel="0" NextCounsel="0" Completed="1">Name</Name>
<Type>#3 Student (Main)</Type>
<Description>Bible Study</Description>
</Item>
<Item>
<Name>Name</Name>
<Type>Assistant</Type>
<Description>Bible Study</Description>
</Item>
</StudentItems>
</W20160411>
</AssignmentHistory>
Now, in my XSL script I link into the above document like this (just a snippet for now):
<tr>
<td class="cellComments" colspan="4">
<xsl:variable name="AssignHistory" select="document('AssignHistory.xml')"/>
<xsl:variable name="week" select="Date/#NextWeek"/>
<xsl:variable name="NextReviewQuestion" select="$AssignHistory/AssignmentHistory/*[name()=$week]/ReviewQuestion"/>
<xsl:if test="normalize-space($NextReviewQuestion) != ''">
<span class="textReviewQuestionLabel">
<xsl:value-of select="//Labels/NextReviewQuestion"/>
</span>
<span class="textReviewQuestion">
<xsl:value-of select="$NextReviewQuestion"/>
</span>
<br />
</xsl:if>
<br />
<br />
<br />
<span style="font-size: 8pt;">
<xsl:apply-templates select="$AssignHistory/AssignmentHistory/*[name()=$week]/StudentItems">
<xsl:with-param name="MainHall" select="//Labels/MainHall"/>
<xsl:with-param name="AuxClass1" select="//Labels/AuxClass1"/>
<xsl:with-param name="AuxClass2" select="//Labels/AuxClass2"/>
</xsl:apply-templates>
</span>
</td>
</tr>
Now this is the issue. See the week: <W20160404/>? This week was a special event. We didn't have a meeting because we all went somewhere else for a assembly. As a result, there is no details.
So this is what I want to do:
If the week that I am trying to get details from is empty (special event) attempt to get the value from the next sibling instead (if there is one). Otherwise, if it is not empty (a normal meeting) just use the returned value like I do now.
It does get a bit more complicated for the students bit of script. But the principle is the same. To use the following sibling if required.
I am sure I have worded this much more complicated than it needs to be.
Update
I will reform the question in due course.
Here is a history snippet:
<?xml version="1.0" encoding="utf-8"?>
<AssignmentHistory Version="171804">
<W20160229>
<ReviewQuestion>Why will God’s Kingdom have to crush the earthly rulerships depicted in the image? (Da 2:44)</ReviewQuestion>
</W20160229>
<W20160404/>
<W20160411>
<ReviewQuestion>What did the immense tree in Nebuchadnezzar’s dream represent? (Da 4:10, 11, 20-22)</ReviewQuestion>
</W20160411>
<W20170803>
<ReviewQuestion>Test question</ReviewQuestion>
</W20170803>
</AssignmentHistory>
Here is the main XML snippet:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="TestTransform.xsl"?>
<MeetingWorkBook>
<Meeting>
<Date ThisWeek="W20160229" NextWeek="W20160404">Date 1</Date>
</Meeting>
<Meeting>
<Date ThisWeek="W20160404" NextWeek="W20160411">Date 2</Date>
</Meeting>
<Meeting>
<Date ThisWeek="W20160411" NextWeek="W20170803">Date 3</Date>
</Meeting>
</MeetingWorkBook>
Here is the simplified XSL snippet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
</head>
<body>
<table>
<xsl:for-each select="MeetingWorkBook/Meeting">
<tr>
<td>
<xsl:value-of select="Date/#ThisWeek"/>
</td>
<td>
<xsl:value-of select="Date/#NextWeek"/>
</td>
<td>
<xsl:variable name="AssignHistory" select="document('TestHist.xml')"/>
<xsl:variable name="week" select="Date/#NextWeek"/>
<xsl:variable name="NextReviewQuestion" select="$AssignHistory/AssignmentHistory/*[name()=$week]/ReviewQuestion"/>
<xsl:if test="normalize-space($NextReviewQuestion) != ''">
<xsl:text>Question: </xsl:text>
<xsl:value-of select="$NextReviewQuestion"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Now, if you view the main XML file in IE you will get:
W20160229 W20160404
W20160404 W20160411 Question: What did the immense tree in Nebuchadnezzar’s dream represent? (Da 4:10, 11, 20-22)
W20160411 W20170803 Question: Test question
This shows the problem. The dates are fictional. So this is the context where I want to use the following sibling "ReviewQuestion" if the first attempt returns an empty node.
Update 2
Based on your excellent revision to your answer I was able to make the simpler bit of my script work as expected. I broke down the code a bit more as I needed a conditional label prefix "Question: ". So at the moment I have:
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
</head>
<body>
<table>
<xsl:for-each select="MeetingWorkBook/Meeting">
<tr>
<td>
<xsl:value-of select="Date/#ThisWeek"/>
</td>
<td>
<xsl:value-of select="Date/#NextWeek"/>
</td>
<td>
<xsl:variable name="AssignHistory" select="document('TestHist.xml')"/>
<xsl:variable name="week" select="Date/#NextWeek"/>
<xsl:variable name="history-week" select="$AssignHistory/AssignmentHistory/*[name()=$week]"/>
<xsl:variable name="NextReviewQuestion" select="($history-week | $history-week/following-sibling::*)/ReviewQuestion"/>
<xsl:if test="normalize-space($NextReviewQuestion) != ''">
<xsl:text>Question: </xsl:text>
<xsl:value-of select="$NextReviewQuestion"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
My only remaining bit to address now is that I originally also had this code:
<xsl:apply-templates select="$AssignHistory/AssignmentHistory/*[name()=$week]/StudentItems">
<xsl:with-param name="MainHall" select="//Labels/MainHall"/>
<xsl:with-param name="AuxClass1" select="//Labels/AuxClass1"/>
<xsl:with-param name="AuxClass2" select="//Labels/AuxClass2"/>
</xsl:apply-templates>
I need to do the same thing again now. We need to use the following sibling "StudentItems" if the first one returned nothing.
Then we are done.
Consider the following simplified example:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="AssignmentHistory">
<table border="1">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'W')]">
<tr>
<td>
<xsl:value-of select="name()" />
</td>
<xsl:choose>
<xsl:when test="*">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="following-sibling::*[*][1]/*"/>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:template>
<xsl:template match="ReviewQuestion">
<td>
<xsl:value-of select="." />
</td>
</xsl:template>
<xsl:template match="StudentItems">
<!-- ??? -->
</xsl:template>
</xsl:stylesheet>
When applied to the given XML example, the result (rendered) will be:
Added:
Regarding the problem presented in the Update part of your question:
Try replacing this part:
<td>
<xsl:variable name="AssignHistory" select="document('TestHist.xml')"/>
<xsl:variable name="week" select="Date/#NextWeek"/>
<xsl:variable name="NextReviewQuestion" select="$AssignHistory/AssignmentHistory/*[name()=$week]/ReviewQuestion"/>
<xsl:if test="normalize-space($NextReviewQuestion) != ''">
<xsl:text>Question: </xsl:text>
<xsl:value-of select="$NextReviewQuestion"/>
</xsl:if>
</td>
with:
<td>
<xsl:variable name="AssignHistory" select="document('TestHist.xml')"/>
<xsl:variable name="week" select="Date/#NextWeek"/>
<xsl:variable name="history-week" select="$AssignHistory/AssignmentHistory/*[name()=$week]"/>
<xsl:value-of select="($history-week | $history-week/following-sibling::*)[normalize-space(ReviewQuestion)][1]/ReviewQuestion"/>
</td>
In below Code I have xml input which shows booktypes.I want to arrange book types according to there types in each columns. Some columns have values some not. Check expected output.
Input
<?xml version="1.0" encoding="UTF-8"?>
<BookTypes>
<Types>
<string>T1</string>
<string>T3,M1,P1</string>
<string>T2,P2</string>
<string>M3,P3</string>
</Types>
</BookTypes>
XSLT script: Current xslt script gives me result but not as expected.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="types">
<type>T</type>
<type>M</type>
<type>P</type>
</xsl:variable>
<xsl:variable name="types-set" select="exsl:node-set($types)" />
<xsl:template match="/">
<table>
<tr>
<th>T Type</th>
<th>M Type</th>
<th>P Type</th>
</tr>
<xsl:for-each select="BookTypes/Types/string">
<tr>
<xsl:variable name="splitValue">
<xsl:apply-templates/>
</xsl:variable>
<xsl:for-each select="exsl:node-set($splitValue)/*">
<xsl:variable name="mySplittedValue" select="." />
<xsl:for-each select="$types-set/type">
<xsl:variable name="my-types" select="." />
<td>
<xsl:choose>
<xsl:when test="contains($mySplittedValue, $my-types)">
<xsl:value-of select="$mySplittedValue"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>-</xsl:text>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="text()" name="split">
<xsl:param name="pText" select="."/>
<xsl:if test="string-length($pText) > 0">
<item>
<xsl:value-of select="substring-before(concat($pText, ','), ',')"/>
</item>
<xsl:call-template name="split">
<xsl:with-param name="pText" select="substring-after($pText, ',')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Expected output
<table>
<tr>
<th>T Type</th>
<th>M Type</th>
<th>P Type</th>
</tr>
<tr>
<td>T1</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>T3</td>
<td>M1</td>
<td>P1</td>
</tr>
<tr>
<td>T2</td>
<td>-</td>
<td>P2</td>
</tr>
<tr>
<td>-</td>
<td>M3</td>
<td>P3</td>
</tr>
</table>
Summery: Output
There are three(3) fixed types, P, M, T which are exist in any one input say P3, M3. here P3 contains P (type) so value P3 should come under column name P type. In input there are 3 or 2 or 1 value separed by , comma (say T3,M1,P1). That every value should be split first and then later display in table
I think you are making this more complicated that it needs to be. Try:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="types">
<type>T</type>
<type>M</type>
<type>P</type>
</xsl:variable>
<xsl:variable name="types-set" select="exsl:node-set($types)" />
<xsl:template match="/">
<table>>
<tr>
<xsl:for-each select="$types-set/type">
<th><xsl:value-of select="concat(., ' Type')"/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="BookTypes/Types/string">
<xsl:variable name="my-types" select="." />
<tr>
<xsl:for-each select="$types-set/type">
<td>
<xsl:choose>
<xsl:when test="contains($my-types, .)">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:text>-</xsl:text>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Result:
<table>
<tr>
<th>T Type</th>
<th>M Type</th>
<th>P Type</th>
</tr>
<tr>
<td>T</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>T</td>
<td>M</td>
<td>P</td>
</tr>
<tr>
<td>T</td>
<td>-</td>
<td>P</td>
</tr>
<tr>
<td>-</td>
<td>M</td>
<td>P</td>
</tr>
</table>
I'm getting Attribute match is not allowed on this element errors on all these elements XAML except the root. I think I'm missing something about the syntax...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates match="/Table"/>
<xsl:apply-templates match="/Paragraph"/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table>
<xsl:apply-templates match="TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="TableRowGroup">
<xsl:apply-templates match="TableRow"/>
</xsl:template>
<xsl:template match="TableRow">
<tr>
<xsl:apply-templates match="TableCell"/>
</tr>
</xsl:template>
<xsl:template match="TableCell">
<td>
</td>
</xsl:template>
</xsl:stylesheet>
Use <xsl:apply-templates select="..."/> instead of <xsl:apply-templates match="..."/>.
When I try to transform this XAML document
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Arial" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="12" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0">
<Table CellSpacing="1" Margin="0,0,0,0"><Table.Columns><TableColumn Width="264" /></Table.Columns><TableRowGroup><TableRow><TableCell Padding="0,0,0,0">
<Paragraph FontFamily="Times New Roman" FontSize="10.666666666666666" Margin="0,0,0,0">
<Span FontWeight="Bold"><Run>some text</Run></Span><Run> </Run>
<Span Foreground="#FF00681C"><Run>some more text</Run></Span>
</Paragraph>
</TableCell></TableRow></TableRowGroup></Table>
</Section>
using this XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="/Table"/>
<xsl:apply-templates select="/Paragraph"/>
<xsl:apply-templates select="/Run"/>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table>
<xsl:apply-templates select="TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="TableRowGroup">
<xsl:apply-templates select="TableRow"/>
</xsl:template>
<xsl:template match="TableRow">
<tr>
<xsl:apply-templates select="TableCell"/>
</tr>
</xsl:template>
<xsl:template match="TableCell">
<td>
</td>
</xsl:template>
<xsl:template match="Paragraph">
<p>
<xsl:apply-templates select=""/>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="Run">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="Span">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
</xsl:stylesheet>
i get this incorrect result
<html>
<body>
some text some more text
</body>
I saw a few problems with your XSLT that would stop it working.
There is no namespace in the XSLT. There needs to be a namespace that
matches the one in the input XML, and you need to use this namespace
when matching elements.
Your first template matches "/", which matches the root node. I
assume you actually want to match the document element Section. The
apply-templates inside this are matching elements beginning with
"/", which makes them absolute paths, so they won't match anything.
I've taken a guess at what output XML you expect. The following XSLT stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
version="1.0"
exclude-result-prefixes="ns">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" method="html"/>
<xsl:template match="/ns:Section">
<html>
<body>
<xsl:apply-templates select="ns:Table"/>
</body>
</html>
</xsl:template>
<xsl:template match="ns:Table">
<table>
<xsl:apply-templates select="ns:TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="ns:TableRowGroup">
<xsl:apply-templates select="ns:TableRow"/>
</xsl:template>
<xsl:template match="ns:TableRow">
<tr>
<xsl:apply-templates select="ns:TableCell"/>
</tr>
</xsl:template>
<xsl:template match="ns:TableCell">
<td>
<xsl:apply-templates select="ns:Paragraph"/>
</td>
</xsl:template>
<xsl:template match="ns:Paragraph">
<p>
<xsl:apply-templates select="ns:Span"/>
</p>
</xsl:template>
<xsl:template match="ns:Run">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="ns:Span">
<span>
<xsl:apply-templates select="ns:Run"/>
</span>
</xsl:template>
</xsl:stylesheet>
produces the following output when applied to your example input XML:
<html>
<body>
<table>
<tr>
<td>
<p><span><span>some text</span></span><span><span>some more text</span></span></p>
</td>
</tr>
</table>
</body>
</html>
which may need a little formatting...