i want to transform some xml into HTML that has the following format:
<TR><TD> col1 <TD> col2 <TD> col3 </TR>
Note: The output is HTML, complete with optional closing tags omitted. This is the problem, and the reason the question exists.
A snippet of the XSL i'm using is:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
doctype-system='http://www.w3.org/TR/html4/strict.dtd'
doctype-public='-//W3C//DTD HTML 4.01//EN'
indent='yes'
method='html'
/>
...
<xsl:for-each select="/">
<TR><TD><xsl:value-of select="col1"/><TD><xsl:value-of select="col2"/><TD><xsl:value-of select="col3"/></TR>
</xsl:for-each>
You can see that the guts of the XSL matches my desired HTML (wrapped for easy reading):
<TR> <TD><xsl:value-of select="Column1"/>
<TD><xsl:value-of select="Column2"/>
<TD><xsl:value-of select="Column3"/> </TR>
Note: Those of you who know the error i'm getting from the XSLT: hopefully already know the answer.
When presented with my XSL (which, don't forget, is a form of xml), i get the non-well formed error:
End tag 'TR' does not match the start tag 'TD'.
This makes perfect sense. Indeed:
<TD><xsl:value-of select="Column3"/> </TR>
i do not close the TD element before closing the TR. So the question is:
How can i transform xml into HTML, given that HTML is not xml?
See also
HTML: Include, or exclude, optional closing tags?
XSLT: Transforming into non-xml content?
Omitting optional tags of html
Update one
It has been suggested that one could simply include the closing tags anyway, in order to make the XSL validate (shown wrapped for easy reading):
<TR> <TD><xsl:value-of select="col1"/></TD>
<TD><xsl:value-of select="col2"/></TD>
<TD><xsl:value-of select="col3"/></TD> </TR>
then, by using xsl:output method='html', the final HTML content would have the </TD> tags magically omitted. Except it doesn't work:
<TR><TD>col1</TD><TD>col2</TD><TD>col3</TD></TR>
Update two
It has been suggested that i give up, don't bother asking this question, and just include the optional closing tags. That's possible, but that's not my question. Also, the "solution" doesn't work for elements where the closing tag is forbidden, e.g.:
<BR/>
or
<BR></BR>
How would i include a <BR> element in my HTML output, given that it is forbidden in HTML to close a <BR> element.
Here's one way to do this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<TR><TD><xsl:value-of select="col1"/><TD><xsl:value-of select="col2"/><TD><xsl:value-of select="col3"/></TR>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<col1>1</col1>
<col2>2</col2>
<col3>3</col3>
</t>
the wanted result is correctly produced:
<TR><TD>1<TD>2<TD>3</TR>
I believe the simplest thing is to just accept you're going to have closing tags in the output. While they might be optional, I believe most people would agree that best practice is to include them.
Is there a reason you really don't want optional closing tags in the output?
Re Update Two
There's no problem with this update. With method="html" <BR/> will be output as <BR>:
XSLT (note <BR/>):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
doctype-system='http://www.w3.org/TR/html4/strict.dtd'
doctype-public='-//W3C//DTD HTML 4.01//EN'
indent='yes'
method='html'
/>
<xsl:template match="/">
<HTML><BODY>
<TR>
<xsl:apply-templates/>
</TR>
<BR/> <!-- HERE -->
</BODY></HTML>
</xsl:template>
<xsl:template match="item">
<TD><xsl:value-of select="."/></TD>
</xsl:template>
</xsl:stylesheet>
Input:
<root>
<item>one</item>
<item>two</item>
</root>
Output (note <BR>):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML><BODY>
<TR>
<TD>one</TD>
<TD>two</TD>
</TR>
<BR> <!-- HERE -->
</BODY></HTML>
Have you tried the output as "HTML"? Elements that shouldn't be self-closed in HTML are not (i.e. <BR>, <img>).
If you still don't like how the XSLT engine is serializing HTML output, then you could set your <xsl:output method="text"> and construct the "HTML" that you want:
<TR><TD><xsl:value-of select="col1"/><TD><xsl:value-of select="col2"/><TD><xsl:value-of select="col3"/></TR>
which produces:
<TR><TD>col1<TD>col2<TD>col3</TR>
Ian, have you tried <xsl:output method="text">?
http://www.w3schools.com/xsl/el_output.asp
Related
Is it possible for XSLT preserve anchors and other embedded HTML tags within XML?
Background: I am trying to convert an HTML document into XML with an XSL stylesheet using XSLT. The original HTML document had content interspersed with anchor tags (e.g. Some hyperlinks here and there). I've copied that content into my XML, but the XSLT output lacks anchor tags.
Example XML:
<?xml version="1.0" ?>
<observations>
<observation>Hyperlinks disappear.</observation>
</observations>
Example 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/html">
<xsl:output method="html" indent="yes" encoding="UTF-8"/>
<xsl:template match="/observations">
<html>
<body>
<xsl:value-of select="observation"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output:
<html xmlns="http://www.w3.org/1999/html">
<body>Hyperlinks disappear.</body>
</html>
I've read a few similar articles on stackoverflow and checked out the Identity transform page on wikipedia; I started to get some interesting results using xsl:copy-of, but I don't understand enough about XSLT to get all of the words and tags embedded within each XML element to appear in the resulting HTML. Any help would be appreciated.
Write a separate template to match a elements, copy their attributes and content.
What is wrong with your approach? In your code,
<xsl:value-of select="observation"/>
simply sends to the output the string value of the observation element. Its string value is the concatenation of all text nodes it contains. But you need not only the text nodes in it, but also the a elements themselves.
The default behaviour of an XSLT processor is to "skip" element nodes, because of a built-in template. So, if you do not mention a in a template match, it is simply ignored and only its text content is output.
Stylesheet
Note: This stylesheet still relies on the default behaviour of the XSLT processor to some extent. The order of events will resemble the following:
The template where match="/observations" is matched. It adds html
and body to the output. Then, a template rule must be found for the
content of observations. A built-in template matches observation,
does nothing with it, and looks for a template to process its content.
For the a element, the corresponding template is matched, with
copies the element and attributes. Finally, a built-in template copies
the text nodes inside observation and a.
<?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" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/observations">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="a">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML Output
<html>
<body>Hyperlinks disappear.
</body>
</html>
Hi I have two xsl files and I have one xml how can I combine these xsl files together at transform type and combine them it and get one html
index.html
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " "><!ENTITY bull "•">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="hello.xsl"/>
<xsl:template match="/">
<html>
<tr>
<td><xsl:value-of select="name" /></td>
</tr>
</html>
</xsl:template>
</xsl:stylesheet>
and then my send xsl is
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " "><!ENTITY bull "•">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table>
<tr>
<td><xsl:value-of select="age" /></td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
and my xml is
<xml>
<name>abc</name>
<age>15</age>
</xml>
What I want output is like
<html>
<tr><td>abc</td></tr>
<table>
<tr><td>15</td></tr>
</table>
</html>
Is that is do able thing to perform in xsl I search so many site but couldn't find answer, plz help
EDIT: You edited your question and are now asking something completely different.
As I said, you can combine templates and other element from separate stylesheets with xsl:include and xsl:import. See the relevant section of the specification here.
There are ways to combine separate stylesheets (e.g. via xsl:include and xsl:import), but in your case I do not think it is even necessary.
Your stylesheets only have one template each and they simply retrieve values from an input XML which is a trivial action. There is really no need to store those two templates in separate stylesheets.
Write one stylesheet that produces both the html element and the table.
Let me emphasize another thing: It is evident in your question that you do not really understand the workings of both XSLT and HTML. To give a few hints:
the output you request is malformed HTML. A tr element cannot be an immediate child of html. Content must be placed inside body, as opposed to header.
both of the templates you show match /. Obviously, it makes no sense to combine them if they match the same node.
Please take the time to study the basics of XSLT and HTML before asking a new question.
Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html" indent="yes"/>
<xsl:template match="/xml">
<html>
<body>
<table border="solid">
<tr>
<xsl:for-each select="*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</tr>
<tr>
<td>
<xsl:value-of select="*[1]"/>
</td>
<td>
<xsl:value-of select="*[2]"/>
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output
<html>
<body>
<table border="solid">
<tr>
<td>name</td>
<td>age</td>
</tr>
<tr>
<td>abc</td>
<td>15</td>
</tr>
</table>
</body>
</html>
In the following stylesheet:
<?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>
<h1>Music Collection:</h1>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<td><xsl:value-of select="catalog/cd/title" disable-output-escaping="yes" /></td>
<td><xsl:value-of select="catalog/cd/artist" /></td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Why does it not convert the < to < when used with the following HTML?
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
<cd>
<title>Empire Burlesque < </title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia </company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
The output can be tested here.. http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=tryxsl_value-of
Edit
Here is another example where it does not work
<xsl:for-each select="//productType">
<xsl:value-of select="." disable-output-escaping="yes" />
<br></br>
</xsl:for-each>
With the DOE the < get stripped out. Without it i can see the < character (Using XSLT 1.0)
disable-output-encoding was an optional feature in XSLT 1 (and is deprecated in XSLT 2) so a processor is allowed to ignore it. In particular it is almost always ignored in any processing pipeline in which the output from XSLT is passed as an in-memory tree (a DOM node for example) to a following application which then serialises the XML. d-o-e is essentially a hint to the XSLT serialisation phase and in such a processing pipeline XSLT serialisation is not used.
It is something processor-related (a bug I'd say) - using the .NET XSLT processor in Visual Studio I get < as expected, and I get < if I remove disable-output-escaping="yes"
The effect of disable-output-escaping depends on what processor you are using and on the way in which you are using it. You haven't given us enough information to answer these questions.
More pertinently, why are you using it? What problem are you trying to solve? Usually, when people use disable-output-escaping, they are going about things the wrong way - there's a better approach available. There are some cases where d-o-e is appropriate, but it means you can only use the stylesheet with a processor that supports it, in a pipeline where you know that the stylesheet's result tree is being piped straight into a serializer rather than into some other tree-consuming process.
Here is my xml:
<Catalog>
<catalogDetail catalogId="DemoCatalog">
<catalogName>Demo Catalog</catalogName>
</catalogDetail>
<catalogDetail catalogId="GoogleCatalog">
<catalogName>Google Catalog</catalogName>
</catalogDetail>
</Catalog>
I want it to be read in HTML file how can I do this???
To do this your HTML file should contain some JavaScript code, so you will want to learn how to parse XML in Javascript.
Here is a good StackOverflow question on this topic: XML parsing in JavaScript
You can do by using PHP's XML Library called simplexml for more information check this link
http://www.w3schools.com/php/php_xml_simplexml.asp
NOTE : If you can elaborate on what technology you're using, I'll try to provide a more complete example.
I would suggest using XSLT for this. With XSLT, you can pass in the XML fragment, parse it, and return formatted HTML.
Here's an example XSLT document that converts XML to HTML:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I'm trying to use a .xsl file so that it will return a HTML table of the XML document. I have no experience with this and it is something I've not done before so it's probably this is just a simple mistake.
I have the following code for my podcatalog.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Tranform">
<xsl:template match="/">
<html>
<body>
<h2>Pods Papers</h2>
<table border="1">
<tr bgcolor="#9ACD32">
<th>Author</th>
<th>Title</th>
<th>Pages</th>
<th>Year</th>
</tr>
<xsl:for-each select="pods-papers/inproceedings">
<tr>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="pages"/></td>
<td><xsl:value-of select="year"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
And the podcatalog.xml can be found here
The error I am getting is: "Error loading stylesheet: Parsing an XSLT stylesheet failed."
Change:
<xsl:for-each select="pods-papers/inproceedings key">
to:
<xsl:for-each select="pods-papers/inproceedings">
'key' is an attribute of element
It looks like you’re defining entities the wrong way (<!ENTITY Aring "Å" > should have & instead of &) and, more seriously, without a DTD. It appears to be a longstanding request that we should be able to do that, but... So the problem is that your XML file has a DOCTYPE declaration that contains just entity definitions, not a document type definition.
The options appear to be:
Write a DTD. Some work, but might be useful for documentation purposes.
Replace the entity references by the characters themselves or by character references, e.g. Ö by Ö or by Ö.