Cannot get xslt to output an (&) even after escaping the character

44,924

Solution 1

You can combine disable-output-escaping with a CDATA section. Try this:

<xsl:text disable-output-escaping="yes"><![CDATA[&]]></xsl:text>

Solution 2

I am trying to create a query string of variable assignments separated by the & symbol (ex: "var1=x&var2=y&..."). I plan to pass this string into an embedded flash file.

I am having trouble getting an & symbol to show up in XSLT.

Here is a runnable, short and complete demo how to produce such URL:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:variable name="vX" select="'x'"/>
 <xsl:variable name="vY" select="'y'"/>
 <xsl:variable name="vZ" select="'z'"/>

  <xsl:template match="/">
    <xsl:value-of select=
"concat('http://www.myUrl.com/?vA=a&amp;vX=', $vX, '&amp;vY=', $vY, '&amp;vZ=', $vZ)"/>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any source XML document (ignored):

<t/>

the wanted, correct result is produced:

http://www.myUrl.com/?vA=a&vX=x&vY=y&vZ=z

As for the other issues raised in the question:

If I type &amp; with no tags around it, then the output of the document is &amp; with no change.

The above statement simply isn't true ... Just run the transformation above and look at the result.

What really is happening:

The result you are seeing is absolutely correct, however your output method is html or xml (the default value for method=), therefore the serializer of the XSLT processor must represent the correct result -- the string http://www.myUrl.com/?vA=a&vX=x&vY=y&vZ=z -- as (part of) a text node in a well-formed XML document or in an HTML tree.

By definition in a well-formed XML document a literal ampersand must be escaped by a character reference, such as the built-in &amp; or &#38;, or &#x26;

Remember: A string that is represented as (part of) an XML text node, or within an HTML tree, may not look like the same string when represented as text. Nevertheless, these are two different representations of the same string.

To better understand this simple fact, do the following:

Take the above transformation and replace the xsl:output declaration:

 <xsl:output method="text"/>

with this one:

 <xsl:output method="xml"/>

Also, surround the output in a single XML element. You may also try to use different escapes for the ampersand. The transformation may now look like this:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" method="xml"/>

 <xsl:variable name="vX" select="'x'"/>
 <xsl:variable name="vY" select="'y'"/>
 <xsl:variable name="vZ" select="'z'"/>

  <xsl:template match="/">
        <t>
            <xsl:value-of select=
 "concat('http://www.myUrl.com/?vA=a&amp;vX=', $vX, '&#38;vY=', $vY, '&#x26;vZ=', $vZ)"/>
        </t>
  </xsl:template>
</xsl:stylesheet>

And the result is:

<t>http://www.myUrl.com/?vA=a&amp;vX=x&amp;vY=y&amp;vZ=z</t>

You will get the same result with output method html.

Question:

Is the URL that is output different (or even "damaged") than the one output in the first transformation?

Answer:

No, in both cases the same string was output -- however in each case a different representation of the string was used.

Question:

Must I use the DOE (disable-output-escaping="yes") attribute in order to output the wanted URL?

Answer:

No, as shown in the first transformation.

Question:

Is it recommended to use the DOE (disable-output-escaping="yes") attribute in order to output the wanted URL?

Answer:

No, using DOE is a bad practice in XSLT and usually a signal that the programmer doesn't have a good grasp of the XSLT processing model. Also, DOE is only an optional feature of XSLT 1.0 and it is possible that your XSLT processor doesn't implement DOE, or even if it does, you could have problems running the same transformation with another XSLT processor.

Question

I came from a different problem to the question i made a bounty for. My problem: i try to generate this onclick method:

    <input type="submit" 
onClick="return confirm('are you sure?') && confirm('seriously?');" />

what i can make is: i can place the confirms in a function ... but its buggin me that i can not make a & inside a attribute! The solve of this question is the solve of my problem i think.

Answer

Actually, you can specify the && Boolean operation inside a JavaScript expression inside an attribute, by representing it as &amp;&amp;

Here is a complete example, that everyone can run, as I did on three browsers: Chrome, Firefox 41.1.01 and IE11:

HTML:

<!DOCTYPE html> 

    <html> 
      <head> 
        <link rel="stylesheet" href="style.css"> 
        <script src="script.js"></script> 
      </head> 
      <body> 
        <h1>Hello Plunker!</h1> 
        <input type="submit" 
onClick="alert(confirm('are you sure?') &amp;&amp; confirm('seriously?'));" /> 
      </body> 
    </html>

JavaScript (script.js):

function confirm(message) { 
  alert(message); 
  return message === 'are you sure?'; 

}

When you run this, you'll first get this alert:

enter image description here

Then, after clicking the OK button, you'll get the second alert:

enter image description here

And after clicking OK you'll finally get the alert that produces the result of the && operation:

enter image description here

You may play with this code by varying the values of the arguments passed to the confirm() function and you will verify that the produced results are those of using the && operator.

For example, if you change the <input> element to this:

<input type="submit" 
onClick="alert(confirm('really sure?') &amp;&amp; confirm('seriously?'));" /> 

You'll get first this alert:

enter image description here

And when you click OK, you'll immediately get the final result of the && operation:

enter image description here

The second alert is skipped, because the 1st operand of the && operation was false and JavaScript is shortcutting an && where the 1st operand is false.

To summarize:

It is easy to use the && operator inside an attribute, in an HTML document generated by XSLT, by specifying the && operand as &amp;&amp;

Solution 3

Are you expressing the URI in HTML or XHTML? e.g. <tag attr="http://foo.bar/?key=value&amp;key2=value2&amp;..."/> If so, "&amp;" is the correct way to express an ampersand in an attribute value, even if it looks different from than literal URI you want. Browsers will decode "&amp;" and any other character entity reference before either loading them or passing them to Flash. To embed a literal, lone "&" directly in HTML or XHTML is incorrect.

I also personally recommend learning more about XML in order to think about these kinds of things in a clearer way. For instance, try using the W3C DOM more (for more than just trivial Javascript); even if you don't use it day-to-day, learning the DOM helped me think about the tree structure of XML correctly and how to think about correctly encoding attributes and elements.

Solution 4

Use disable-output-escaping="yes" in your value-of tag

Solution 5

If you are creating a query string as part of a larger URL in an attribute of some other tag (like "embed"), then you actually want the & to be escaped as &amp;. While all browsers will figure out what you mean and Do The Right Thing, if you were to pass your generated doc to a validator it would flag the un-escaped & in the attribute value.

Share:
44,924
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I am trying to create a query string of variable assignments separated by the & symbol (ex: "var1=x&var2=y&..."). I plan to pass this string into an embedded flash file.

    I am having trouble getting an & symbol to show up in XSLT. If I just type & with no tags around it, there is a problem rendering the XSLT document. If I type &amp; with no tags around it, then the output of the document is &amp; with no change. If I type <xsl:value-of select="&" /> or <xsl:value-of select="&amp;" /> I also get an error. Is this possible? Note: I have also tried &amp;amp; with no success.

  • Grim
    Grim over 8 years
    Tried this, network transports a &amp; instead of a &
  • Grim
    Grim over 8 years
    I came from a different problem to the question i made a bounty for. My problem: i try to generate this onclick method: <input type="submit" onClick="return confirm('are you sure?') && confirm('seriously?');" /> what i can make is: i can place the confirms in a function ... but its buggin me that i can not make a & inside a attribute! The solve of this question is the solve of my problem i think.
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, Just use: <input type="submit" onClick="return confirm('are you sure?') &amp;&amp; confirm('seriously?');" /> -- it is easy to verify that the value of the onClick attribute is exactly the wanted string. Just run this transformation: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/*"> <xsl:value-of select="@onClick"/> </xsl:template> </xsl:stylesheet> against this XML document: <input type="submit" onClick="return confirm('are you sure?') &amp;&amp; confirm('seriously?');" />
  • Grim
    Grim over 8 years
    Javascript tells me amp is undefined.
  • Flynn1179
    Flynn1179 over 8 years
    @PeterRader You could always fall back on DeMorgan's laws- use onclick="return !(!confirm('are you sure?') || !confirm('seriously?'));". No & to worry about :)
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, I have a proof. I defined and ran this in plncr: <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> </head> <body> <h1>Hello Plunker!</h1> <input type="submit" onClick="alert(confirm('are you sure?') &amp;&amp; confirm('seriously?'));" /> </body> </html> And on clicking the button, the alert() correctly displays: false . The JS itself is: function confirm(message) { alert(message); return message === 'are you sure?'; } So, there is nothing wrong using the &amp; builtin reference.
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, Continuation of the prev. comment: And I played by setting the js function to return false or true -- in all cases the correct result of the Boolean operation was produced by the alert(). Try this yourself, and you'll see. Conclusion: Let this argument be put once and forever to its true conclusion.
  • Grim
    Grim over 8 years
    @DimitreNovatchev what browser are you using?
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, Chrome in this case, but I can test also with IE11 and Firefox -- just need 5 hours to return home from work
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, Yes, I ran successfully the same example both with IE11 and with FireFox 41.0.1. I am glad you now have a working examples how to specify the && Boolean operation inside an attribute of html generated by XSLT. Seems like this completely answers your question, or isn't it?
  • Dimitre Novatchev
    Dimitre Novatchev over 8 years
    @PeterRader, I updated the answer and it shows completely how to specify an && operator inside an attribute of an element of an HTML document generated by XSLT. Does this solve your problem?
  • Palec
    Palec over 8 years
    @PeterRader: Generally speaking, when you’re embedding snippets of one language into another one, you have to apply escaping on each level. A string in JavaScript in an HTML onclick attribute in a PHP string is a typical example. Quotes inside the string have to be escaped to form a correct JavaScript string. The whole JavaScript snippet has to be escaped (PHP htmlspecialchars()) to be embedded in the HTML attribute. And the HTML must be further escaped to be embedded in the PHP string (backslashes, quotes, …). Dimitre is right that you should escape & in the onclick attribute.
  • Peter Dolland
    Peter Dolland over 5 years
    Ok, I see xalan has an extra switch -TEXT for text formatting. With this one, the output is as described above.