Generate boolean custom attribute for HTML5 in XSLT - html

Im working with XSLT and I'm outputting an HTML5 document. In my document I need a custom attribute.
I want to achieve this:
<div class="row" data-template>...</div>
So far I have managed to do it using CDATA, like so:
<xsl:text disable-output-escaping="yes"><![CDATA[<div class="row" data-template></div>]]></xsl:text>
Whilst this produces valid markup, the problem arises here when you need to work with the actual node, such as setting the ID dynamically. One of my cohorts suggested the following output:
<div class="row" data-template=""></div>
using:
<xsl:attribute name="data-template" />
Again this is valid, but looks somewhat ugly. Is there another method that allows me to output valid custom data attributes for HTML5?

You might want to live with the fact that <xsl:attribute> produces a name-value pair attribute but make it semantically sensible as a boolean value.
<xsl:attribute name="data-template">true</xsl:attribute>
should produce
<div class="row" data-template="true"></div>
which looks a little less ugly.

Did you already tried:
<xsl:attribute name="data-template">data-template</xsl:attribute>
However I think is not possible to get rid of key-value pairs

Related

Using data-* attribute with Thymeleaf

Can I set data-* attribute with Thymeleaf?
As I understood from Thymeleaf documentation I tried:
<div th:data-el_id="${element.getId()}"> <!-- doesn't work -->
<div data-th-el_id="${element.getId()}"> <!-- doesn't work -->
Yes, th:attr to the rescue Thymeleaf documentation - Setting attribute values.
For your scenario, this should do the job:
<div th:attr="data-el_id=${element.getId()}">
XML rules do not allow you to set an attribute twice in a tag, so you can't have more than one th:attr in the same element.
Note: If you want more that one attribute, separate the different attributes by comma:
<div th:attr="data-id=${element.getId()},data-name=${element.getN‌​ame()}">
With Thymeleaf 3.0 there is the Default Attribute Processor which can be used for any kind of custom attributes, e.g. th:data-el_id="" becomes data-el_id="", th:ng-app="" becomes ng-app="" and so on. There is no need for the beloved data attribute dialect anymore.
This solution I prefer, if I want to use json as the value, instead of:
th:attr="data-foobar='{"foo&quot:'+${bar}+'}'"
You can use (in combination with literal substitution):
th:data-foobar='|{"foo":${bar}}|'
Update: If you don't like the th namespace, you can also use HTML5 friendly attribute and element names like data-th-data-foobar="".
If someone is interested, related template engine tests can be found here: Tests for Default Attribute Processor
Or you can use this Thymeleaf dialect https://github.com/mxab/thymeleaf-extras-data-attribute and you'll be able do
<div data:el_id="${element.getId()}">

XSLT strange behavior with umlaut (mutation)

I have a very strange behavior when I got mutations in a node in xml when I try to parse it with an XSLT.
So we now assume that CustomerName has the Value 'MÖP'.
In this case, the resulting HTML 'a' tag would have a href to 'M%C3%B6P'
<a href="{CustomerName}">
<xsl:value-of disable-output-escaping="yes" select="CustomerName"/>
</a>
In this case, the resulting HTML 'div' tag would have an id 'MÖP'
<div style="display:none">
<xsl:attribute name="id"><xsl:value-of select="CustomerName"/></xsl:attribute>
</div>
It seems like the attribute href in the a tag has something to do with it.
My question is, why is it like that ?
An what can i do that in both cases i got the same output ?
Greetz
The XSLT processor is doing you a favour by escaping the URL value in the href attribute of the HTML link element. This is by design, see http://www.w3.org/TR/xslt-xquery-serialization/#HTML_ESCAPE-URI-ATTRIBUTES. If you really don't want that and you use an XSLT 2.0 processor then you can use <xsl:ouput method="html" escape-uri-attributes="no"/> in your stylesheet.

Import an HTML table using XSL

I have constructed an XSL file that parses an XML formatted log and generates an HTML page with information from the log. In this same XSL file, I am attempting to use XSL to pull in an external HTML file that contains a table that I want to display. As it stands, I can display the entire page that contains the table, but am unable to isolate the table. How can this be done? Currently, I can pull in the entire page using the following code:
<xsl:copy-of select="document($tablePageUrl)" />
However, I don't understand how to traverse the HTML body and pull out a copy of the table. An example of how the HTML document is formatted (the document is proper XML, but not proper HTML):
<html>
<head>
</head>
<body>
<table>
Table Contents
</table>
</body>
</html>
Sounds like you want to use XPath to select a particular element in the document.
Try something like:
<xsl:copy-of select="document($tablePageUrl)/html/body/table" />
From comments:
I had tried using XPath but was using
incorrect syntax
From http://www.w3.org/TR/xpath/#node-sets
The / and // operators compose an
expression and a relative location
path. It is an error if the expression
does not evaluate to a node-set. The
/ operator does composition in the
same way as when / is used in a
location path
In particular, this syntax:
document($tablePageUrl)/html/body/table
Following the production:
PathExpr ::= FilterExpr '/' RelativeLocationPath
FilterExpr ::= PrimaryExpr
PrimaryExpr ::= FunctionCall
Check to see whether the HTML is in a namespace. (Look for a telltale xmlns="....".) Your sample isn't in a namespace, but from experience, if people don't realise that namespaces matter, they often remove the namespace declaration when posting samples. If the elements are in a namespace, then the XPath expression needs to use prefixed names to select them.
<xsl:variable name="source-html" select="document('url')" />
<xsl:value-of select="$source-html//table" />

XSLT string with HTML entities - How can I get it to render as HTML?

I'm completely new to using XSL, so if there's any information that I'm neglecting to include, just let me know.
I have a string in my XSLT file that I can display like this:
<xsl:value-of select="#Description/>
and it shows up, rendered in a browser like:
<div>I can't do anything about the html entities existing in the text.</div> <div>This includes quotes, like "Hello World" and sometimes whitespaces. </div>
What can I do to get this string rendered as html, so that <div></div> results in newlines, " gives me ", and gives me a space?
I could elaborate on things I've already tried that haven't worked, but I don't know if that's relevant.
I think you want to set the following attribute as so:
<xsl:value-of select="#Description" disable-output-escaping="yes"/>
Why do you need to have entities output? To the browser is the same as   -- in both cases it will display a non-breaking space.
There is a feature in XSLT 2.0 called character-maps, that provide this functionality, if really needed. It is an XSLT best practice to try not to use DOE, unless absolutely necessary.
Also, DOE is not a mandatory feature of XSLT and some XSLT processors may not implement it. This means that an XSLT application that uses DOE is generally not portable across different XSLT processors.
The reason divs in HTML get an endline is completely different and related to the CSS boxmodel. Most browsers apply the style:
div {display:block;}
In lieu of the standard display:inline;. However, they only do that to divs in the XHTML namespace. You need to output divs to the XHTML namespace to faciliate that. Bind the XHTML namespace to the prefix xhtml at the top of your document like so:
<xsl:stylesheet xmnls:xhtml="http://www.w3.org/1999/xhtml" ... >
And then output the divs as <xhtml:div> ... </xhtml:div> most browsers would recognise the div to be in the XHTML namespace (http://www.w3.org/1999/xhtml) and apply the block style.

HTML element with double attribute

(The question below is hypothetical, but for reading convenience I'll ask as if I'm actually doing it)
I'm building a site in HTML 5. Unfortunately, IE doesn't support HTML5 elements like "header" and "nav". I was hoping it would treat them like generic "div"'s, but it doesn't. It simply acts as if they aren't there (meaning no CSS is applied to them).
I'd like to fix this by serving IE some dynamically transformed HTML. I'll just use the regular string replacement functions (of PHP, not that it matters) to replace all occurences of
<header>
with
<div class="header>
and so forth (an I'll transform the CSS accordingly). This should be fine, but what about this:
<header class="foo">
With the simplest replace code, this would become
<div class="header" class="foo">
Is that legal in HTML? And will the attribute then end up being "header foo" or just one of them?
(Yes, I do know that the normal way to get multiple classes is
<div class="header foo">
)
No, you can only have one class attribute - like this:
<div class="header foo">
If you have two or more class attributes, I think it just uses the first one.
If this is processed as XHTML it will be not-well-formed and throw an error and I would expect any conformant HTML parser to do this.
While it does rely on the client having JavaScript enabled, there is a method to get IE to work more properly with the new HTML5 elements:
http://remysharp.com/2009/01/07/html5-enabling-script/