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.
Related
I have XML that has encoded HTML data. I am trying to render the data but can't seem to figure out how. Best I can tell is I need to disable-output-escaping="yes" twice but not sure how to do that.
For example, this is a snippet of my XML:
<root>
<node value="<b>body</b>" />
</root>
My XSLT is outputting HTML. Here is the rendered output (the HTML source) with various options
<xsl:value-of select="#value" /> outputs <b>hi</b>
<xsl:value-of select="#value" disable-output-escaping="yes" /> outputs <b>hi</b>
I would like it to output <b>hi</b> to the HTML source so its actually rendered as a bolded hi. Does that make sense? Is that possible?
Escaping is the process of turning < into <. If you disable escaping, it will leave < as <. What you want to achieve is to turn < into <, which would normally be called "unescaping".
In the normal course of events, a parser performs unescaping, while a serializer performs escaping. So if you want to unescape characters, you need to put them through a parsing process, which means you need to take the content of the #value attribute and put it through an operation like fn:parse-xml-fragment() in XPath 3.0, or an equivalent extension function in your chosen processor.
Assuming Sharepoint as a Microsoft .NET product uses XslCompiledTransform you could try to implement the unescaping and parsing with extension "script" (C# or VB or JScript.NET code embedded in XSLT) as follows:
<?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"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="msxsl mf">
<msxsl:script language="C#" implements-prefix="mf">
<msxsl:using namespace="System.IO"/>
public string Unescape(string input)
{
XmlDocument doc = new XmlDocument();
XmlDocumentFragment frag = doc.CreateDocumentFragment();
frag.InnerXml = input;
return frag.InnerText;
}
public XPathNavigator ParseXml(string xmlInput)
{
using (StringReader sr = new StringReader(xmlInput))
{
return new XPathDocument(sr).CreateNavigator();
}
}
</msxsl:script>
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node">
<div>
<xsl:copy-of select="mf:ParseXml(mf:Unescape(#value))" />
</div>
</xsl:template>
</xsl:stylesheet>
If you have access to an XSLT processor (like any version of Saxon 9.7 or Exselt or the latest Altova or XmlPrime) supporting the XPath 3 functions parse-xml and parse-xml-fragment you can write that template without extension functions (in a version="3.0" stylesheet) as
<xsl:template match="node">
<div>
<xsl:copy-of select="parse-xml(string(parse-xml-fragment(#value)))"/>
</div>
</xsl:template>
Output your result with disable-output-escaping, then treat it again in another XSL with disable-output-escaping.
I have the following XSLT file that is already working with the XML file we have on ActiveMQ. The thing is that we are upgrading the system and we don't have the XML view anymore. Instead we have an URL that return in JSON the queue informations.
<?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>PROJECT Notification</h2>
<div style="width:600px;background-color:#e5eecc;border:1px solid #98bf21;margin:10px;">
<table border="1" style="border-style:dashed">
<tr bgcolor="#9acd32">
<th width="300px;">Queue Name</th>
<th>Queue Size</th>
</tr>
<xsl:apply-templates select="queues" />
</table>
</div>
</body>
</html>
</xsl:template>
<xsl:template match="queue">
<tr>
<td><xsl:value-of select="#name"/></td><td><xsl:value-of select="./stats/#size" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
I want to know if that's possible to keep using this same XSLT file, just modifying the tags to start reading from the JSON URL instead.
I'm using camel to route to this XSLT, but I didn't want to create a Processor to convert the JSON to XML. Instead I want to use the JSON right away.
XSLT operates on XML input, not JSON input. (While you could parse JSON using XSLT 2.0 string processing facilities, it's still not the right tool for the job.)
Your HTML target is quite simple, so migrating away from XML/XSLT shouldn't be as much of a challenge as it could have otherwise been. Look into a JavaScript-based templating engine such as Mustache.js, Handlebars.js, Underscore.js, Hogan.js...
i am making a website that will feature many articles that will always be changing, i am trying to find a way to quickly change the text in these articles as i am the only person who knows the code in the company.
I was thinking of having a text document or something that has the articles text and when it gets changed so does the text on the site.I just dont know how to implement this.
sorry if its hard to understand what i mean, im not too familiar with sleep these days.
You don't need any dynamic server code like the other answers are suggesting. Either a "static site generator" (there are uncountably many, but that should give you something to Google if my main answer doesn't satisfy you) or a client-side scripting.
XSLT was designed for this exact problem. It can be run client-side or server-side with xsltproc (for compatibility with dumb clients). XSLT 1.0 is well-supported by all common browsers, though if you need EXSLT extensions in IE you had to add shims. Note that Webkit-based browsers can't do XSLT on file:// URLs, either set up a local HTTP server or use Firefox.
I have a minimal example site set up here that includes multiple files in
one page: https://o11c.github.io/foo-test/foo-root.xml
foo-style.xml:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/index">
<html>
<body>
<h2>Merge test</h2>
<table border="1">
<tr>
<th>Attr</th>
<th>Value</th>
</tr>
<xsl:apply-templates select="document(include/#name)"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="root">
<xsl:for-each select="foo">
<tr>
<td><xsl:value-of select="#x"/></td>
<td><xsl:value-of select="text()"/></td>
</tr>
</xsl:for-each>
</xsl:template>
<xsl:template name="identity">
<xsl:copy>
<xsl:for-each select="node()|#*">
<xsl:call-template name="identity"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
foo-root.xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="foo-style.xslt"?>
<index>
<include name="foo-1.xml"/>
<include name="foo-2.xml"/>
</index>
foo-1.xml:
<?xml version="1.0"?>
<root>
<foo x="a">aa</foo>
<foo x="b">bb</foo>
<foo x="c">cc</foo>
</root>
foo-2.xml:
<?xml version="1.0"?>
<root>
<foo x="d">dd</foo>
<foo x="e">ee</foo>
<foo x="f">ff</foo>
</root>
Further resources:
XSLT 1.0 spec
XPath 1.0 spec - in particular the function reference
EXSLT extensions - node-set in particular is very useful.
xsltproc webpage
You could use wordpress, if you are building the site from scratch and not adding to an existing one. This will allow you to edit articles in a user friendly interface that will allow you to style the text and will be easier for other people in the company to edit as well. It's very fast to set up.
Or you could just keep the written text in the HTML file itself, but this may make it harder to maintain and style, and those not technical savvy may not be able to edit it or will end up breaking it.
Well you might do this using php and Mysql
You can easily display save the articles in mysql and you could create a simple user interface for the people respnsible for editing the code to edit it too easy
I would like to use a single XSL to produce multiple output formats (xml and html for now)
I would like to define which output format by means of a stylesheet
So the code I have is as follows:
<xd:doc scope="stylesheet">
<xd:desc>
<xd:p><xd:b>Created on:</xd:b> July 1, 2015</xd:p>
<xd:p><xd:b>Author:</xd:b> me</xd:p>
<xd:p>A stylesheet to test the application of XYZABC</xd:p>
<xd:p>takes a single parameter - xslt_output_format</xd:p>
<xd:p>valid inputs - xml html</xd:p>
</xd:desc>
</xd:doc>
<xsl:output name="xml_out" encoding="UTF-8" indent="yes" method="xml" />
<xsl:output name="html_out" encoding="ISO-8859-1" indent="yes" method="html"/>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$xslt_output_format = 'xml'">
<data>
<p>This is some test xml output</p>
</data>
</xsl:when>
<xsl:when test="$xslt_output_format = 'html'">
<html>
<head>
<title>HTML Test Output</title>
</head>
<body>
<p>This is some test html output</p>
</body>
</html>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
If I pass 'xml' as the parameter I get
This is some test xml output
and if I pass 'html' I get
HTML Test Output
This is some test html output
That doesn't seem to respect my respect for ISO-8859-1 encoding on the html (which I was just using to test the was working)
Michael Kay's XSLT 2.0 and Xpath 2.0 tome is a little vague and definitely short of examples on using multiple statements (sorry Mike)
So I am just asking am I using it correctly?
Can I achieve what I am aiming for?
TIA
Feargal
I think you need to use xsl:output together with xsl:result-document http://www.w3.org/TR/xslt20/#creating-result-trees, so try along the lines of
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$xslt_output_format = 'xml'">
<xsl:result-document format="xml_out" href="output.xml">
<data>
<p>This is some test xml output</p>
</data>
</xsl:result-document>
</xsl:when>
<xsl:when test="$xslt_output_format = 'html'">
<xsl:result-document format="html_out" href="output.html">
<html>
<head>
<title>HTML Test Output</title>
</head>
<body>
<p>This is some test html output</p>
</body>
</html>
</xsl:result-document>
</xsl:when>
</xsl:choose>
</xsl:template>
I would probably use templates and modes to distinguish the two different ways of processing but the advice on using xsl:output and xsl:result-document remains the same.
xsl:output by itself doesn't allow you to make any run-time selection of output method.
In 2.0 you can use xsl:output in conjunction with xsl:result-document: the xsl:result-document can select a named xsl:output declaration, or it can override some of its attributes selectively.
Another option (also available in 1.0) is to override xsl:output from the calling API: if you're using JAXP look at Transformer.setOutputProperty().
On the Saxon command line you can set output properties using the syntax !indent=yes on the command line (the "!" needs to be "\!" with some shells).
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