xsl trying to ouput '<' as opposed to &

2019-03-28 11:11发布

问题:

Update:

The issue still persists although it is not quite the same as before. Below is an example of what is being input, what is being output and what I want to have output

An example of the input:

&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;font-size: medium&amp;quot;&amp;gt;Product description text&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;

Current output:

&lt;p&gt;&lt;span style="font-size: medium"&gt;Product description text&lt;/span&gt;&lt;/p&gt;

Intended output:

<p><span style="font-size: medium">Product description text</span></p>

.

Using CDATA has helped as it allows me to input '<' but as seen in the output above, even when using disable-output-escaping, it has changed in the output

.

.

Original question:

The error I'm getting is "'<', hexadecimal value 0x3C, is an invalid attribute character"

What I'm trying to do is replace all occurrences of &lt ; and &gt ; with < and > respectively.

To keep this as simple as possible, here is the code for just lt;:

<xsl:variable name="lt">
  <xsl:text><</xsl:text>
</xsl:variable>
<xsl:variable name="lthex">&amp;lt;</xsl:variable>
<xsl:copy-of select="ew:replacestring(products_description/node(),$lthex,$lt)"/>

I've tried various things in place of text e.g. value-of etc.

I know there's nothing wrong with the code format and the vb code linked to it because I'm using it multiple times to replace and output elsewhere

The problem with this though is that I want < and > to literally be ouput, not a code which is then seen by the browser and changed

.

If you need more information just ask (I'm struggling to explain this very well)

Any help will be appreciated

回答1:

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

This is because < is illegal (and that's why your app is complaining). For >, you can use:

<xsl:text disable-output-escaping="yes">></xsl:text>


回答2:

The original problem

An example of the input:

&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;font-size: medium&amp;quot;&amp;gt;Product description text&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;

Intended output:

<p><span style="font-size: medium">Product description text</span></p>

What you really seem to have is double escaped input so instead of just simple outputting the text with disable-output-escaping="yes" you need some ways to do string replacing. Clearly it seems that you do the replacing with ew:replacestring() extension function. The problem is that even if you manage to replace &amp;lt; with <, the result is still only a string and the < character gets escaped on output.

Your original replacement text code was not well-formed because < as such is seen as markup. Using

<xsl:variable name="lt">
  <xsl:text><![CDATA[<]]></xsl:text>
</xsl:variable>

or

<xsl:variable name="lt">
  <xsl:text>&lt;</xsl:text>
</xsl:variable>

are equivalent and fix that problem. However this doesn't help in the problem that the replacement character still is outputted as an entity reference. Using disable-output-escaping="yes" here in the variable definition has no effect on that problem either.

<xsl:variable name="lt">
  <xsl:text disable-output-escaping="yes">&lt;</xsl:text>
</xsl:variable>

<xsl:variable name="lt">
  <xsl:value-of select="&lt;" disable-output-escaping="yes">
</xsl:variable>

These code examples don't work because disable-output-escaping="yes" only has an effect when the value is serialized, not when a variable gets assigned.

A possible fix

What you could try to do is to store the result of your text replacing into a variable

<xsl:variable name="replaced-text">
    <xsl:copy-of select="ew:replacestring(products_description/node(),$lthex,$lt)"/>
</xsl:variable>

and then output the value of this variable with disable-output-escaping="yes"

<xsl:value-of select="$replaced-text" disable-output-escaping="yes"/>

Another solution without extension functions

I was able to transform your input

&amp;lt;p&amp;gt;&amp;lt;span style=&amp;quot;font-size: medium&amp;quot;&amp;gt;Product description text&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;

to this output

<p><span style="font-size: medium">Product description text</span></p>

with a slightly modified version of Jeni Tennison's acronym replacement template. In your case the document containing the acronym titles would look like this

<acronyms>
    <acronym acronym="&amp;lt;">&lt;</acronym>
    <acronym acronym="&amp;gt;">></acronym>
    <acronym acronym="&amp;amp;">&amp;</acronym>
    <acronym acronym="&amp;apos;">'</acronym>
    <acronym acronym="&amp;quot;">"</acronym>
</acronyms>

The required modification would be to change this part of the code example

<acronym title="{$acronyms[1]}">
    <xsl:value-of select="$acronym" />
</acronym>

to look like this

<xsl:value-of select="$acronyms[1]" disable-output-escaping="yes"/>

That template should work in every environment because it is XSLT 1.0 and it doesn't require any extension functions.



回答3:

Edit: It looks like you're trying to take a serialization of an XML or HTML serialization as input instead of an XML or HTML serialization, and expect it to output an XML or HTML serialization?

The correct thing would be to fix your broken input, but see How to unescape XML characters with help of XSLT?


You have some kind of misunderstanding here. XSL takes XML as input and outputs HTML or XML. < is represented as &lt; in serialized HTML and XML.

An HTML or XML file that contains a < that does not start a tag is an incorrect serialization (not wellformed).

&lt; is the correct representation of < in an HTML or XML file.

An HTML or XML file is only a serialization of the data it represents. That is, it's one level below the data it represents. You should think of the contents of the HTML or XML as what the data represents (<), not as the serialization of the data (&lt;).

Try instead to explain why you think having &lt; is a problem, so we can correct the misunderstanding?