I have the status in the third column but its value is coming on the first column... How do I change that?
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>status</th>
</tr>
<xsl:for-each select="catalog/cd[artist='Bob Dylan']">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
<xsl:for-each select="catalog/cd/dude" >
<tr>
<td><xsl:value-of select="status"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Basically it's coming out like:
Title Artist status
Empire Burlesque Bob Dylan
hello
I want:
Title Artist status
Empire Burlesque Bob Dylan hello
How do I go about doing that?
This is the source XML:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
<dude>
<status>hello</status>
</dude>
</cd>
</catalog>
You were creating a separate row for status. Since you have three columns in one row, you should add the dude column together with the other two to obtain what you desire:
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>status</th>
</tr>
<xsl:for-each select="catalog/cd[artist='Bob Dylan']">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td><xsl:value-of select="dude/status"/></td>
</tr>
</xsl:for-each>
</table>
This iterates in all cd elements which contain an artist child element with the text Bod Dylan, and when it finds one, it adds a <tr> table row containing three <td> table cells which are your columns.
The way you were doing it iterated in all dude elements (there is only one) and placed the contents of the status element in a new <tr> row. That's why you got an extra row.
Related
Am trying to generating PDF out of XML document. Please find my below XML and XSL for the same.
Am expecting it should display all rows under tag but am getting only very first element (rows) in each tag.
Please find my below xml
<receipt>
<order>
<page></page>
<page>
<line_number>1</line_number>
<product_code>S10</product_code>
<line_number>2</line_number>
<product_code>S20</product_code>
<line_number>3</line_number>
<product_code>S92</product_code>
</page>
<page>
<line_number>6</line_number>
<product_code>S92</product_code>
<line_number>7</line_number>
<product_code>S31</product_code>
<line_number>8</line_number>
<product_code>S31</product_code>
</page>
</order>
</receipt>
Please find my xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/receipt">
<html>
<head>
<style>#page {size: a4 landscape;}</style>
</head>
<body>
<table >
<thead>
<tr >
<th >Line</th>
<th>Item Code</th>
</tr>
</thead>
<xsl:for-each select="order/page" >
<tbody>
<tr style="font-size: 9px; ">
<td ><xsl:value-of select="line_number" /></td>
<td ><xsl:value-of select="product_code" /></td>
</tr>
</tbody>
</xsl:for-each>
</table>
<br />
</body>
</html>
</xsl:template>
</xsl:stylesheet>
In the output only 1st element in tag is coming instead of all the elements (rows) under each tag.
for example :
output :
1 s10
6 s92
Expected Output
1 s10
2 s20
3 s92
6 s92
7 s31
8 s31
You want to output one row per line_number, rather that one row per page, so you xsl:for-each needs to select these line_number elements
<xsl:for-each select="order/page/line_number">
Then to get the value of the line_number and following product_code, do this...
<td><xsl:value-of select="." /></td>
<td><xsl:value-of select="following-sibling::product_code[1]" /></td>
Try this...
<xsl:template match="/receipt">
<html>
<head>
<style>#page {size: a4 landscape;}</style>
</head>
<body>
<table >
<thead>
<tr>
<th>Line</th>
<th>Item Code</th>
</tr>
</thead>
<tbody>
<xsl:for-each select="order/page/line_number">
<tr style="font-size: 9px; ">
<td><xsl:value-of select="." /></td>
<td><xsl:value-of select="following-sibling::*[1][self::product_code]" /></td>
</tr>
</xsl:for-each>
</tbody>
</table>
<br />
</body>
</html>
</xsl:template>
Note that this does make the assumption that each line_number will be followed by a product_code.
(I have also moved the creation of the tbody element outside the xsl:for-each as you should really only have one such element in your table, rather than one for each row)
Hello I was struggling with this for the past days and I could not find a good answer nor solution. I have an XML file with a list of objects like this:
<?xml version="1.0" encoding="UTF-8"?>
<LineItems>
<TableName>Lines</TableName>
<TableTerm>Lines</TableTerm>
<LineItems>
<Class>A Class</Class>
</LineItems>
<LineItems>
<Number>1234</Number>
</LineItems>
<LineItems>
<Description>G</Description>
</LineItems>
<LineItems>
<Class>B Class</Class>
</LineItems>
<LineItems>
<Number>5678</Number>
</LineItems>
<LineItems>
<Description>F</Description>
</LineItems>
<ColumnMetadata>
<Name>Class</Name>
<Term>Class</Term>
</ColumnMetadata>
<ColumnMetadata>
<Name>Number</Name>
<Term>No</Term>
</ColumnMetadata>
<ColumnMetadata>
<Name>Description</Name>
<Term>Description</Term>
</ColumnMetadata>
</LineItems>
I am applying the following transformaiton:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:variable name="columns" select="count(LineItems/ColumnMetadata)" />
<xsl:variable name="items" select="count(LineItems/LineItems)" />
<xsl:variable name="rows" select="$items div $columns" />
<table border="1">
<thead >
<tr bgcolor="#9acd32">
<xsl:for-each select="LineItems/ColumnMetadata">
<th style="padding: .3em 0;">
<xsl:value-of select="Term" />
</th>
</xsl:for-each>
</tr>
</thead>
<tbody style="text-align: center;">
<xsl:for-each select="(//LineItems)[position()<=$rows]">
<xsl:variable name="i" select="position() - 1"/>
<tr>
<xsl:for-each select="(//*)[position()<=$columns]">
<xsl:variable name="j" select="position()+($columns*$i)"/>
<td style="padding: .3em 0;">
<xsl:value-of select="LineItems/LineItems[$j]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Finally the desire output for this case would be:
<table>
<thead>
<tr>
<th>Class</th>
<th>No</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>A Class</td>
<td>1234</td>
<td>G</td>
</tr>
<tr>
<td>B Class</td>
<td>5678</td>
<td>F</td>
</tr>
</tbody>
</table>
This case is a case of MxN table, I cna know how many columns from nodes. So, to sumarise:
The actual list that have to be transformed as a table is all inside root <LineItems>.
I don't know how many items (rows) I am going to get, but I can calculate them dividing amount of <LineItems> nodes ($items) by amount of <ColumnMetadata> nodes ($columns)
Nodes like <Class>, <Number> and <Description>, are columns in table, but they can have other names, they are dynamic and can be 5, 6... Many columns.
If I transform above XML with XSL in online tools I only get the header row of the table (and inspecting HTML, I can see 2 rows for 2 items, but empty). If I use Visual Studio transformation tool, I not only get header row, I also get first 2 columns of table (in this example Class values) but not the values in the rest of them. I really don't understand what is going on and why do I get different results using different tools.
Thanks in advance
lineitmes folllow a regular pattern.
Then I believe it could be simply:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/LineItems">
<xsl:variable name="columns" select="count(ColumnMetadata)"/>
<table border="1">
<thead >
<tr>
<xsl:for-each select="ColumnMetadata">
<th>
<xsl:value-of select="Term"/>
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="LineItems[position() mod $columns = 1]">
<tr>
<xsl:for-each select=". | following-sibling::LineItems[position() < $columns]">
<td>
<xsl:value-of select="*"/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
I have an XML file which i got by exporting a database. now i need to show the xml data in html page as a table. to do so, i have to check the corresponding values for a particular data in the XML file from an XSLT file. since my database is a bit complicated, i am facing difficulties in checking the multiple values of differnt nodes and selecting a corresponding values from another node of the xml file. e.g. i have the following xml data-
<?xml-stylesheet type='text/xsl' href='myXSL.xsl'?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name1>
<names>
<id>5</id>
<class>space</class>
<from>Germany</from>
<fm>
<id>9</id>
<names>5</names>
<name>Vienna</name>
</fm>
<fm>
<id>10</id>
<names>5</names>
<name>Prague</name>
</fm>
</names>
</name1>
<FFrom>
<effect>
<id>11</id>
<DVV>1</DVV>
<SAT>0</SAT>
<DDCC>0</DDCC>
<name>SAA Name</name>
</effect>
<effect>
<id>23</id>
<DVV>0</DVV>
<SAT>0</SAT>
<DDCC>1</DDCC>
<name>SAA Name2</name>
</effect>
</FFrom>
<name2>
<newNames>
<id>1</id>
<name>VSSS Name</name>
<route1>
<id>5</id>
<identifyer>C</identifyer>
<function>abc</function>
<names>4</names>
<naviagtes2>
<id>9</id>
<fm>7</fm>
<effect>2</effect>
</naviagtes2>
<naviagtes2>
<id>10</id>
<fm>8</fm>
<effect>5</effect>
</naviagtes2>
</route1>
</newNames>
<newNames>
<id>6</id>
<name>VEE Name</name>
<route1>
<id>18</id>
<identifyer>C0</identifyer>
<function>abc</function>
<names>5</names>
<naviagtes2>
<id>68</id>
<fm>9</fm>
<effect>11</effect>
</naviagtes2>
<naviagtes2>
<id>69</id>
<fm>10</fm>
<effect>7</effect>
</naviagtes2>
</route1>
</newNames>
</name2>
</root>
I used the following xslt codes
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title>title</title>
<style type="text/css">
body {
font: 10px Verdana, sans-serif;
color: #000000;
margin: 0;
padding: 0;
}
tr.header2 {
font-style:italic;
}
tr.newNames{
background-color:#6495ED;
margin-top:4px;
}
</style>
</head>
<body><h1><xsl:value-of select="Title" /></h1>
<table width="800px" class="table" cellspacing="0px">
<xsl:for-each select="root/name2/newNames">
<tr class="newNames"><td colspan="12">
<b>NNavigate:</b> <xsl:value-of select="name"/><br/>
<b>NMNaviagate:</b> <xsl:value-of select="route1/function"/>
</td></tr>
<xsl:for-each select="/root/name1/names">
<tr class="names"><td colspan="12">
<b> CClass: </b><xsl:value-of select="class" />
<b> FFrom: </b><xsl:value-of select="from" />
</td></tr>
<tr class="header2">
<td>Route</td>
<td>From</td>
<td align="center">SA</td>
<td align="center">DB</td>
</tr>
<xsl:for-each select="fm">
<tr>
<td class=""><xsl:value-of select="name" /></td>
<td class=""><xsl:value-of select="/root/FFrom/effect/name" /></td>
<td class=""><xsl:value-of select="/root/FFrom/effect/SAT" /></td>
<td class=""><xsl:value-of select="/root/FFrom/effect/DVV" /></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I am stuck in the following point.
if you notice there are fm nodes, effect nodes and naviagtes2 nodes.
in my html page, there will be a table where values of first column come from fm nodes (root/name1/names/fm/name) and values of second column come from effect nodes (root/FFrom/effect/name). in the naviagtes2 nodes, there are fm and effect elements which are equivalent to fm/id and effect/id. that is, naviagtes2 nodes are used to check which values of effect/name will be against fm/name in the table. conditions are like following
root/name1/names/fm/name against root/FFrom/effect/name if
root/name1/names/fm/id = root/name2/newNames/route1/naviagtes2/fm and
root/FFrom/effect/id = root/name2/newNames/route1/naviagtes2/effect
i am new in XSLT programming. Could anyone give me any clue please how to solve that in XSLT ?
in the naviagtes2 nodes, there are fm and effect elements which are
equivalent to fm/id and effect/id. that is, naviagtes2 nodes are used
to check which values of effect/name will be against fm/name in the
table.
I am afraid I still don't understand your question, but in an effort of moving this forward, I'll take a stab (in the dark?) at it.
The following stylesheet uses keys to link each naviagtes2 node to the fm and effect elements whose ids are listed in the naviagtes2 node. Thus each naviagtes2 node creates a {fm,effect} "pair" and these pairs are listed in the resulting table, along with the values fetched from the paired elements:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="fm" match="name1/names/fm" use="id" />
<xsl:key name="effect" match="FFrom/effect" use="id" />
<xsl:template match="/">
<table border="1" >
<tr>
<th>id</th>
<th>fm id</th>
<th>effect id</th>
<th>fm name</th>
<th>effect name</th>
</tr>
<xsl:for-each select="root/name2/newNames/route1/naviagtes2">
<tr>
<td><xsl:value-of select="id" /></td>
<td><xsl:value-of select="fm" /></td>
<td><xsl:value-of select="effect" /></td>
<td><xsl:value-of select="key('fm', fm)/name" /></td>
<td><xsl:value-of select="key('effect', effect)/name" /></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
when applied to your example input, the result is:
<?xml version="1.0" encoding="UTF-8"?>
<table border="1">
<tr>
<th>id</th>
<th>fm id</th>
<th>effect id</th>
<th>fm name</th>
<th>effect name</th>
</tr>
<tr>
<td>9</td>
<td>7</td>
<td>2</td>
<td/>
<td/>
</tr>
<tr>
<td>10</td>
<td>8</td>
<td>5</td>
<td/>
<td/>
</tr>
<tr>
<td>68</td>
<td>9</td>
<td>11</td>
<td>Vienna</td>
<td>SAA Name</td>
</tr>
<tr>
<td>69</td>
<td>10</td>
<td>7</td>
<td>Prague</td>
<td/>
</tr>
</table>
which in HTML would be rendered as:
Hopefully this gets you closer to your goal.
I'm brand new to markup languages and need to display an HTML table, convert it to XML then display it using XSL looking the same as the HTML. Here's a bit of the HTML table:
<table border="1"
cellpadding="5"
summary="Obesity and other statistics">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<tr>
<td>Mississippi</td>
<td>34.4%</td>
<td>17.8%</td>
<td>$36,919</td>
<td>80.4%</td>
</tr>
4 columns, and several rows with 1 title row. Has a summary (not necessary, can be removed for ease), cell padding and a border. Here's the start of the XML table:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="mg.xsl"?>
<data>
<columns>
<State>State</State>
<Obese_adults>Obese adults</Obese_adults>
<Obese_children_and_adolescents>Obese children and adolescents</Obese_children_and_adolescents>
<Median_Household_Income>Median Household Income</Median_Household_Income>
<H_S_Graduation_rate>H.S Graduation rate</H_S_Graduation_rate>
</columns>
<records>
<record>
<State>Mississippi</State>
<Obese_adults>34.4%</Obese_adults>
<Obese_children_and_adolescents>17.8%</Obese_children_and_adolescents>
<Median_Household_Income>$36,919</Median_Household_Income>
<H_S_Graduation_rate>80.4%</H_S_Graduation_rate>
</record>
That was converted following a guideline which may or may not be any good for what I'm trying to do. Couldn't find any clear explanation on what it all does or how to use it with the xsl either.
Here's what I have of the XSL
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2></h2>
<table border="1">
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<xsl:for-each select="data/records/record">
<tr>
<td><xsl:value-of select="State"/></td>
<td><xsl:value-of select="Obese adults"/></td>
<td><xsl:value-of select="Obese children and adolescents"/></td>
<td><xsl:value-of select="Median Household Income"/></td>
<td><xsl:value-of select="H.S Graduation rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
which was again formed following a template I found. I have an idea of what it's doing, but not what it's doing wrong and why it isn't working. I would appreciate some help, especially if I am far off of what is the correct way to go about doing this. Thanks
edit: error I'm getting is "Error loading stylesheet: XPath parse failure: operator expected:" by the way.
You have some small mistakes in ur XSLT here is the edited one of yours;
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2></h2>
<table border="1">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<xsl:for-each select="data/records/record">
<tr>
<td><xsl:value-of select="State"/></td>
<td><xsl:value-of select="Obese_adults"/></td>
<td><xsl:value-of select="Obese_children_and_adolescents"/></td>
<td><xsl:value-of select="Median_Household_Income"/></td>
<td><xsl:value-of select="H_S_Graduation_rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
the output of this applied to your XML will be;
<html>
<body>
<h2></h2>
<table border="1">
<tr>
<th>State</th>
<th>Obese adults</th>
<th>Obese children and adolescents</th>
<th>Median Household Income</th>
<th>H.S Graduation rate</th>
</tr>
<tr>
<td>Mississippi</td>
<td>34.4%</td>
<td>17.8%</td>
<td>$36,919</td>
<td>80.4%</td>
</tr>
</table>
</body>
</html>
XML file:
<books>
<scifi key=...>
<author>Don Larson</author>
<title>The Edge</title>
<year>...</year>
</scifi>
<scifi key=...>
<author>Don Larson</author>
<author>James Kiddleton</author>
<author>Danny Wobers</author>
<title>Incognitum</title>
<year>1987</year>
</scifi>
<scifi key=...>
<author>....</author>
<author>....</author>
<title>...</title>
<year>...</year>
</scifi>
etc......................
</books>
XSL file:
<xsl:template match="/">
<html>
<body>
<center><h1>SciFi</h1>
<table border="1">
<tr>
<th>Title</th>
<th>Authors</th>
<th>Year</th>
</tr>
<xsl:for-each select="books/scifi">
<xsl:sort select="year"/>
<tr>
<td><center><xsl:value-of select="title"/></center></td>
<td>
<xsl:for-each select="author">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</td>
<td><xsl:value-of select="year"/></td>
</tr>
</xsl:for-each>
</table>
</center>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
When the above table is displayed, for each cell containing a title, the cell next to it contains all the authors related to that title
eg:
Title Authors Year
(1cell) (1cell) (1cell)
----- ------- ----
Don Larson
Incognitum James Kiddleton 1987
Danny Wobers
Now what I want to do is for each title display the authors (if there is more than one that is..) related to it in separate cells and get something like this instead:
Title Authors Year
(3cells) (3cells) (3cells)
----- ------- ----
Incognitum Don Larson 1987
Incognitum James Kiddleton 1987
Incognitum Danny Wobers 1987
Instead of having one cell for title and one cell containing all three authors related to that title, I want to have three cells with the same title and each of those cells can have a cell with the related author next to it.
I still want to keep sorting everything by yeat and I still want the order of my cells (left->right) to be Title->Author->Year
What do I have to change in my XSL file?
you want one row per author, so change
<tr>
<td><center><xsl:value-of select="title"/></center></td>
<td>
<xsl:for-each select="author">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</td>
<td><xsl:value-of select="year"/></td>
</tr>
to
<xsl:for-each select="author">
<tr>
<td><center><xsl:value-of select="../title"/></center></td>
<td>
<xsl:value-of select="."/>
</td>
<td><xsl:value-of select="../year"/></td>
</tr>
</xsl:for-each>
David
Quick fix is
<xsl:template match="/">
<html>
<body>
<center><h1>SciFi</h1>
<table border="1">
<tr>
<th>Title</th>
<th>Authors</th>
<th>Year</th>
</tr>
<xsl:for-each select="books/scifi">
<xsl:sort select="year"/>
<xsl:for-each select="author">
<tr>
<td><center><xsl:value-of select="../title"/></center></td>
<td>
<xsl:for-each select=".">
<p><xsl:value-of select="."/></p>
</xsl:for-each>
</td>
<td><xsl:value-of select="../year"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</center>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
but in the long run I would suggest to move from one template doing it all with nested for-eachs to structured stylesheet with templates mapping each element type to a result and then doing apply-templates to keep going.