I want to combine some XSL with XML and put out the resulting HTML.
My XSl contains this line which doesnt work:
Click here
The desired output would be:
Click here
The code works when I leave out the <xsl:value-of select="row/objectid"/> part in the URL. It also works when I place the <xsl:value-of select="row/objectid"/> outside the hyperlink tag, so i KNOW the value-of-select to be correct by itself.
So I suspect that the quotes are messing things up...how can I fix this?
PS. I tried replacing " with ' as well
Your stylesheet should contain well-formed XML, so you can't include the output from value-of in an attribute. Use an attribute value template instead:
<a href="www.domain.com/account/business/get/?t=2&id={row/objectid}"
>Click here</a>
The expression in curly braces will be evaluated and replaced with its output.
Related
My XSLT stylesheet generates Bootstrap HTML where some elements may contain data-... attributes to pass additional data to the framework. For example, I have this code to generate a popover element:
<xsl:template match="foo">
<a href="#" data-toggle="popover" data-placement="top" data-trigger="hover" data-html="true">
<xsl:attribute name="title">Popover Title</xsl:attribute>
<xsl:attribute name="data-content">This is some additional content.</xsl:attribute>
<xsl:text>Link</xsl:text>
</a>
</xsl:template>
The data-content attribute is supposed to contain additional markup. The resulting output should be something like
Link
How do I generate markup text for the <xsl:attribute> in this case?
(Somewhat related: here and here and here.)
The answers
Thanks for the answers! While I think that kjhughes's answer provides the technically correct solution to implement properly what I need, I think that Ian's answer addresses my question more directly.
You can't put unescaped markup in an attribute value, but you don't need to - if you escape the angle brackets (and any ampersands and quotes-within-quotes) as entity references bootstrap will still render the html properly in the popover.
Link
The simplest way to get this right in the XSLT would be to use a CDATA section:
<xsl:attribute name="data-content"
><![CDATA[This is <em>some</em> additional content
& a link.]]></xsl:attribute>
And the serializer will escape it for you as necessary.
You cannot generate markup inside of an xsl:attribute because XML does not allow unescaped markup inside of attributes.
Specifically, the grammar rule for AttValue prohibits < altogether and & unless the & is part of a properly formed Reference:
AttValue ::= '"' ([^<&"] | Reference)* '"'
| "'" ([^<&'] | Reference)* "'"
Supporting definitions:
Reference ::= EntityRef | CharRef
EntityRef ::= '&' Name ';'
CharRef ::= '&#' [0-9]+ ';'
| '&#x' [0-9a-fA-F]+ ';'
HTML too, even HTML5, does not allow unescaped markup in attribute values.
Adding escaped markup in attribute values is viable but ugly. Especially for heavily marked-up content, I'd recommend creating the content separately and then associating it procedurally via JavaScript rather than declaratively via attribute values. There are many examples of doing this, including this one mentioned in one of your references.
Not an "official" way of doing this, but when using lxml to process the XML and XSLT stylesheets, consider using XSLT extension elements in your stylesheet. Those custom elements allow you to run Python code when elements match during processing, and that code can modify/edit parts of the output document.
I have some XSLT that gets an attribute and sends it as part of the URL to a php $_GET variable. It looks like this:
<xsl:attribute name="href">search.php?subject="<xsl:value-of select="#level1"/>"</xsl:attribute>
It works with most values of #level1. For instance, if the value is foo, I get this url:
search.php?subject="foo"
The problem is, when that value of #level1 contains a quotation mark, like "bar" etc etc it doesn't work. I get this:
search.php?subject=""bar" etc etc"
Which of course returns an empty subject. If I add backslashes, suddenly it works. For instance, if I edit the URL to read:
search.php?subject="\"bar\" etc etc"
then $_GET['subject]=="bar" etc etc! So how can I get XSL to add backslashes to escape these rogue quotation marks? I tried
<xsl:attribute name="href">search.php?subject="<xsl:value-of select='replace(#level1,",\")'/>"</xsl:attribute>
and I tried
<xsl:attribute name="href">search.php?subject="<xsl:value-of select="replace(#level1,",\""/>"</xsl:attribute>
But nothing seems to work yet.
In XSLT 2.0 use the replace() function.
In XSLT 1.0 use the recursive exslt:replace template which you can find at http://www.exslt.org
(And either way, when you ask questions about XSLT, tell us which version you are using).
I have a question!
I have an XML document that has sections and subsections. I am generating a Doxygen page out of it using XSLTProc and now I have a problem. When I generate a section name like this:
<xsl:template match="SECTION/SUBSECTION">
#subsection <xsl:value-of select="#title"/>
<xsl:apply-templates/>
</xsl:template>
Then the first word of the title does not show up, because Doxygen expects the declaration in this way:
#subsection <subsectionname> <subsectiontitle>
So, the first word is automatically treated as the subsection name. Putting a randomly generated string there does not seem like a very simple task. I tried to put unique number instead, by using <xsl:value-of select="count(preceding-sibling::*[#col]) + 1", which worked as expected, but as it turns out, Doxygen does not accept numbers as subsection names. I also tried to strip white spaces of "#title" and use that as the subsection name, but XSLTProc complains that it was not an immediate child of <xslt:stylesheet>. How can I easily put some unique string there? It does not have to be meaningful text.
Thanks in advance!
Use the generate-id() function.
<xsl:value-of select="generate-id(#title)"/>
If you want the generated string to be more "readable", here is one way to do this:
<xsl:value-of select="concat(#title, generate-id(#title))"/>
Sorry if this is a dumb question, but it is possible to store, and retrieve, a HTML snippet within an xsl 1.0 variable? EG:
<xsl:variable name="something"><p>Hi there</p><p>How are you today?</p></xsl:variable>
<xsl:value-of disable-output-escaping="yes" select="$something"/>
It just when I try, it seems to strip the HTML tags out. Thanks.
You need to use <xsl:copy-of select="$something"/> instead of xsl:value-of.
I'll add some explanation of what's happening :)
The reason you're not getting the html tags is that the $something variable contains a dom fragment, not a string: the value-of element extracts the content of the node(s) the same way as the string() function does, so does not serialize the nodes.
This would provide, instead, a string representation of the html string you have and you can then print it out with value-of and disable-output-escaping:
<xsl:variable name="something"><![CDATA[<p>Hi there</p><p>How are you today?</p>]]></xsl:variable>
(see https://msdn.microsoft.com/en-us/library/ms256181(v=vs.110).aspx "The results are converted to a string, as by a call to the string() function")
I am using Umbraco and I need to display an image in a Rss Feed. The feed is generated by Xslt.
Everything works if I do text stuff. Such stuff is technically feasible, but the feed I analyzed had been generated by WordPress.
The challenge is that I have no idea how I can embed within my tag.
I have a variable, say "url", that returns the full url of the underlying image. How can I insert within ? Remember I am using Xslt to achieve the task.
<content:encoded>
<img src="{$url}" />
</content:encoded>
I guess that CDATA must be used, but I am not able to escape correctly illegal characters :(
Thanks for your help.
Roland
roland, you're trying to escape things twice. It's unnecessary (not to mention hideous!) This page shows:
<content:encoded><![CDATA[This is <i>italics</i>.]]></content:encoded>
I.e. they're just escaping the markup inside the <content:encoded> once, and they use CDATA to do that. In your case, CDATA is awkward because you need to substitute $url in the middle. So you could use two CDATA sections wrapped around an <xsl:value-of select="$url" />: (indented for clarity)
<content:encoded>
<![CDATA[<img src="]]>
<xsl:value-of select='$url' />
<![CDATA[">]]>
</content:encoded>
But that would be needlessly verbose. The second CDATA section is unneeded. And we can do better while using the same principle: escape the markup characters (once) that would cause the string to be parsed into a tree. In your case, only the initial < needs to be escaped. You can use < instead of CDATA to escape the <. Put this in your XSLT:
<content:encoded><img src="<xsl:value-of select='$url' />"></content:encoded>
The <xsl:value-of> is not really inside quotes, from XSLT's perspective... those quotes are just the content of text nodes. The <xsl:value-of> works as a normal XSLT instruction.
Change select='$url' to select="concat($siteUrl, photo)" if that's what you need. (I.e. photo is a child element of the context node, and its text value is the name of the image file.)