Turn XML data to HTML table with XSLT - html

I need to be able to turn a flat xml data sets into html tables, and I'm having trouble finding syntax examples that will fit my need. I would like to use one stylesheet that can convert similar looking data sets into html tables with variable columns.
this is a part of my XML File :
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" href="XSLT_StyleSheet.xsl"?> <Services>
<Service WsdlUrl="http://venus.eas.asu.edu/WSRepository/Services/BasicThreeSvc/Service.svc">
<Name>ServiceName</Name>
<Provider></Provider>
<Category>CatName</Category>
<Operations>
<Operaion>
<Name>HelloWorld</Name>
<MsgIn>elloWorldInputMessage</MsgIn>
<MsgOut>HelloWorldOutputMessage</MsgOut>
</Operaion>
<Operaion>
<Name>OP2name</Name>
<MsgIn>InputMessage</MsgIn>
<MsgOut>OutputMessage</MsgOut>
</Operaion>
<Operaion>
<Name>Op3Name</Name>
<MsgIn>InputMessage</MsgIn>
<MsgOut>OutputMessage</MsgOut>
</Operaion>
</Operations>
this how the HTML table must look Like:

If you did not find examples of transforming XML to HTML with XSLT, then you didn't look very hard. That's one of its primary motivations. Anyway, this should get you started:
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*"/>
<xsl:template match="/Services">
<html>
<head>
<title>XSLT example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="Service">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Operations">
<table>
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Type</td>
</tr>
</thead>
<tbody>
<xsl:apply-templates/>
</tbody>
</table>
</xsl:template>
<xsl:template match="Operaion"> <!-- [sic] -->
<xsl:variable name="service" select="ancestor::Service"/>
<tr>
<td><xsl:value-of select="$service/Name"/></td>
<td><xsl:value-of select="Name"/></td>
<td><xsl:value-of select="$service/Category"/></td>
</tr>
</xsl:template>
</xsl:transform>
Output on your (corrected) document (it was missing end tags):
<html>
<head>
<title>XSLT example</title>
</head>
<body>
<table>
<thead>
<tr>
<td>Name</td>
<td>Description</td>
<td>Type</td>
</tr>
</thead>
<tbody>
<tr>
<td>ServiceName</td>
<td>HelloWorld</td>
<td>CatName</td>
</tr>
<tr>
<td>ServiceName</td>
<td>OP2name</td>
<td>CatName</td>
</tr>
<tr>
<td>ServiceName</td>
<td>Op3Name</td>
<td>CatName</td>
</tr>
</tbody>
</table>
</body>
</html>

Related

Browsers don't parse stylesheet properly

I have an XML File:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet hred="remakes.xsl" type="text/xsl" ?>
<remakes>
<remake>
<rtitle>Pygmalion</rtitle>
<ryear>1938</ryear>
<fraction>0.5</fraction>
<stitle>Pygmalion</stitle>
<syear>1937</syear>
</remake>...
and I have created a stylesheet:
?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/remakes">
<html>
<body>
<table border="1">
<tr>
<th>rtitle<</th>
<th>fraction<</th>
<th>stitle<</th>
<th>syear<</th>
</tr>
<xsl:for-each select="remake">
<xsl:value-of select="rtitle"/></td>
<xsl:value-of select="fraction"/></td>
<xsl:value-of select="stitle"/></td>
<xsl:value-of select="syear"/></td>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But browsers don't parse it so instead of a table there is chaos. Is there a mistake in the code?
There are a number of problems with your stylesheet, although they could always be typos with your question, but as there are too many to mention in comments, they are as follows:
The namespace prefix xsl has not been bound. You should type xmlns:xsl="..."
There is a < symbol in each table header <th>rtitle<</th>. If you really wanted this, you should write it as <th>rtitle<</th>, but more likely it should just be <th>rtitle</th>
You have a closing <\td> for each row, but no opening <td> tag.
You also really need to wrap those <td> in a <tr> tag for it to be rendered properly.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/remakes">
<html>
<body>
<table border="1">
<tr>
<th>rtitle</th>
<th>fraction</th>
<th>stitle</th>
<th>syear</th>
</tr>
<xsl:for-each select="remake">
<tr>
<td><xsl:value-of select="rtitle"/></td>
<td><xsl:value-of select="fraction"/></td>
<td><xsl:value-of select="stitle"/></td>
<td><xsl:value-of select="syear"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Transform XML to HTML table

I want to transform xml to html using xsl but I'm struggling to make it work although it should be pretty straightforward.
Input XML:
<EEExport Version="201510" Language="International" LanguageIsoCode="int-INT">
<Navigation>
<Navigation Name="Navigation" NavigationID="E905C889-63EF-431E-BD74-A470685F65E0">
<Navigation Name="Oven" NavigationID="B929861A-57D1-4C20-BE2C-0DC006F4D6CE">
</Navigation>
<Navigation Name="Cooker" NavigationID="643B0A58-D83B-4D8F-9E97-A5C8E572B1E5">
</Navigation>
<Navigation Name="Dishwasher" NavigationID="FAB9B544-109D-4B83-A6E4-25114E1D25BA">
<Product ProductID="887B5B3C-F9C7-4F4A-8E0B-1FC62830C508">
<MasterData>
<Brand>Brand1</Brand>
<ProductCode>911 424 310</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >F55600IM0P</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543317288</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >None</Attribute>
</Container>
</Containers>
</Product>
<Product ProductID="D4DB8281-42D7-4240-8731-220FD728481D">
<MasterData>
<Brand>Brand2</Brand>
<ProductCode>911 536 090</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >ZDT26020FA</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543397303</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >Cutlery Drawer</Attribute>
</Container>
</Containers>
</Product>
</Navigation>
</Navigation>
</Navigation>
</EEExport>
I only want to show specific product fields of category 'Dishwasher'.
Desired output:
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<tr>
<td>Brand1</td>
<td>911 424 310</td>
<td>F55600IM0P</td>
<td>None</td>
</tr>
<tr>
<td>Brand2</td>
<td>911 536 090</td>
<td>ZDT26020FA</td>
<td>Cutlery Drawer</td>
</tr>
</table>
</body>
</html>
Current xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="/EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="/Masterdata/Brand"/></td>
<td><xsl:value-of select="/Masterdata/ProductCode"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Obviously I'm doing something wrong. Any help is greatly appreciated.
There are two problems with your XSLT.
Firstly, when you start an XPath expression with / then this represents the top-level document node, and so the search will be relative to that, and not to the node you are currently positioned on.
So instead of doing this:
<xsl:value-of select="/Masterdata/Brand"/>
Do this:
<xsl:value-of select="Masterdata/Brand"/>
Having said that, this leads on to the second issue. XML and XSLT are case sensitive. In your XML you use MasterData, but in your XSLT you refer to Masterdata. So, the expression should actually be like this:
<xsl:value-of select="MasterData/Brand"/>
Try this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="MasterData/Brand"/></td>
<td><xsl:value-of select="MasterData/ProductCode"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Modifying a XSLT XPATH code for a different output

I need to modify my XSLT code for a different output result. I need to output a table with the sigle, number of students and average.
Here's my XML code :
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet href="class.xsl" type="text/xsl" ?>
<university>
<student><sname>Charlie Parker</name>
<course sigle="INF8430" note="69" />
<course sigle="INF1030" note="65" />
<course sigle="INF1230" note="73" /></student>
<student><name>Miles Davis</name>
<course sigle="INF8430" note="65" />
<course sigle="INF1030" note="77" />
<course sigle="INF1230" note="83" /></student>
<student><name>John Coltrane</name>
<course sigle="INF9430" note="24" />
<course sigle="INF1030" note="64" />
<course sigle="INF1230" note="56" /></student>
<student><name>Charles Mingus</name>
<course sigle="INF8430" note="34" />
<course sigle="INF1230" note="89" /></student>
</university>
Here's my XSLT Code so far :
<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:strip-space elements="*"/>
<xsl:template match="/university">
<html>
<body>
<table border="1">
<tr>
<th>Name</th>
<th>Average</th>
</tr>
<xsl:for-each select="student">
<xsl:sort select="substring-after(name, ' ')"/>
<tr>
<td><xsl:value-of select="name" /></td>
<td><xsl:value-of select="sum(course/#note) div count(course)"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Here's what the output should look like :
Thanks a lot for your help!
Your input document is not well-formed, please be careful when posting questions on Stackoverflow.
The standard approach to identify elements that are unique with respect to their content or one of their attributes is to use a key. The best explanation of this is still on Jeni Tennison's web page.
You could also consider using the round() function if there's too much precision in the average column.
XSLT Stylesheet
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="course-sigle" match="course" use="#sigle"/>
<xsl:template match="/university">
<html>
<body>
<table border="1">
<tr>
<th>Sigle</th>
<th>Number of Students</th>
<th>Average</th>
</tr>
<xsl:for-each select="student/course[count(. | key('course-sigle', #sigle)[1]) = 1]">
<xsl:variable name="count" select="count(key('course-sigle', #sigle))"/>
<tr>
<td>
<xsl:value-of select="#sigle"/>
</td>
<td>
<xsl:value-of select="$count"/>
</td>
<td>
<xsl:value-of select="sum(key('course-sigle', #sigle)/#note) div $count"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
HTML Output
<html>
<body>
<table border="1">
<tr>
<th>Sigle</th>
<th>Number of Students</th>
<th>Average</th>
</tr>
<tr>
<td>INF8430</td>
<td>3</td>
<td>56</td>
</tr>
<tr>
<td>INF1030</td>
<td>3</td>
<td>68.66666666666667</td>
</tr>
<tr>
<td>INF1230</td>
<td>4</td>
<td>75.25</td>
</tr>
<tr>
<td>INF9430</td>
<td>1</td>
<td>24</td>
</tr>
</table>
</body>
</html>
Rendered HTML Output
Including the round function, the output looks like
Besides, if you are in charge of designing this XML document, note that some of the names in it are either incomprehensible ("sigle") or inappropriate given the context ("note"). Proper terms would be "signature" and "grade", or "score".

How to process a namespaced XML document using XSLT?

I am trying to process an XML file with XSLT to produce a list or table or (eventually) an SQL INSERT command with some of the values. I have been using the example from w3schools http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog.
My XML is very simple and I need to extract just the name and the rate of the hotel:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<getHotelsResponse xmlns="http://hotel.booking.vbooking.com">
<getHotelsReturn>
<address>
<number>589-591</number>
<postcode>08014</postcode>
<region>Catalonia</region>
<street>Carrer Vermell</street>
<town>Barcelona</town>
</address>
<name>Downtown Hotel</name>
<rate>235.0</rate>
</getHotelsReturn>
</getHotelsResponse>
</soapenv:Body>
</soapenv:Envelope>
The best XSLT I could build up from the w3schools was this one:
<?xml version="1.0" encoding="utf-8"?>
<!-- Edited by XMLSpyΠ-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/soapenv:Envelope/soapenv:Body/getHotelsResponse">
<html>
<body>
<h2>Hotels in Barcelona</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Hotel name</th>
<th>Rate ($/night)</th>
</tr>
<xsl:for-each select="getHotelsReturn">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Which should produce a similar result to what I had in the w3schools example, but it comes back as blank.
Can anyone please explain this? Thanks.
As pointed out by #keshlam, if elements in your input XML have namespaces, you must declare them in your XSLT stylesheet as well.
Find more detail on namespaces in a previous answer of mine.
The gist of the information you find there is: as far as the XSLT processor is concerned, a getHotelsReturn element is entirely different from a vb:getHotelsReturn element.
Stylesheet
<?xml version="1.0" encoding="utf-8"?>
<!-- Edited by XMLSpy?-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:vb="http://hotel.booking.vbooking.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
exclude-result-prefixes="soapenv vb">
<xsl:template match="/soapenv:Envelope/soapenv:Body/vb:getHotelsResponse">
<html>
<body>
<h2>Hotels in Barcelona</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Hotel name</th>
<th>Rate ($/night)</th>
</tr>
<xsl:for-each select="vb:getHotelsReturn">
<tr>
<td><xsl:value-of select="vb:name"/></td>
<td><xsl:value-of select="vb:rate"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output
<html>
<body>
<h2>Hotels in Barcelona</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Hotel name</th>
<th>Rate ($/night)</th>
</tr>
<tr>
<td>Downtown Hotel</td>
<td>235.0</td>
</tr>
</table>
</body>
</html>
Rendered HTML
You can use XPaths like this:
/Product1/Product2/Product3[#ValidYN = 'Y' and #ProductType = 'ABC']
/Product1/Product2/Product3[#ValidYN = 'Y' and #ProductType = 'DEF']
/Product1/Product2/Product3[#ValidYN = 'Y' and #ProductType = 'GHI']
Check this other question How to parse XML using XSLT?

Displaying an XML file with XSL to look like HTML

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>