views:

360

answers:

4

I've got an XSL template that outputs text as opposed to XML. In this text, I need to include ASCII character 0x10 in certain position.

I understand this character is not allowed in an XML document, but I'm going to output text, so why am I not allowed to use it anyway?

I also understand it will not be possible to put this character literally into the template, neither within a CDATA section nor as &#16;. But why does on-the-fly generation not work either? I tried, for instance, to define a function that returns this char and used it as <xsl:value-of select="z:get_char(16)"/> but that produces an Invalid character exception either.

Is there a way?

+4  A: 

Since the XSLT file is an XML file, you cannot include that character reference. I don't think you can do this in a pure XSLT solution.

The ASCII character HEX 10/DEC 16 is the Data Link Escape (DLE) control character.

The XML Spec only allows the three whitespace(tab, carriage return, line feed) control characters.

Legal characters are tab, carriage return, line feed, and the legal characters of Unicode and ISO/IEC 10646.

Everything else under 0x20 is not allowed.

Character Range 2 Char ::=
#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

One option is to put a placeholder token value for that character in your output, and then use an external process to find/replace your token with the character.

Mads Hansen
A: 

In the past, I have used this technique to enter a linefeed into an XHTML generated textarea. If I didn't put at least one character, the textarea would self close (causing browser issues). Notice the character is wrapped in <xsl:text>. Also, the original source was on one line, but I formatted for readability.

<textarea name="qry" rows="4" cols="50" id="query">
 <xsl:value-of select="$qry" /><xsl:text>&#x0A;</xsl:text>
</textarea>
Kevin Hakanson
Well, but Linefeed is one of the legal characters, which puts your code in a different situation …
Christopher Creutzig
+2  A: 

If you can use XML 1.1 (which allows inserting such characters in an XML document as a character reference) then the following should work, at least it works for me with Sun Java 6 and Saxon 9.2:

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:output method="text"/>

  <xsl:template name="main">
    <xsl:text>&#x10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>
Martin Honnen
Alas, I'm using XSLCompiledTransform in .NET. Version 1.1 is not supported there. But +1 nevertheless.
GSerg
+1  A: 
Martin Honnen
Excellent. The only change I had to make is adding `disable-output-escaping="yes"` to the `xsl:text`, otherwise the character would appear in the output as an entity `` and I want it as a character.
GSerg
It is even possible without disable-output-escaping, as long as you use xsl:output method="text" and use a slight change in the .NET code. I will edit my answer to show that change.
Martin Honnen
Great! Can't upvote again. But then, is it required to use `using` on those? `using` is an equivalent of calling `Dispose` in `finally`, and you can't call it directly because it is `protected`; therefore, `using` has no effect and you only have to call `Close`?
GSerg
I think the 'using' statement is the right approach with objects implementing IDisposable but it is certainly not crucial to the topic of this thread, namely to be able to use character references of control characters in XML 1.0 stylesheets to output text files with control characters with the .NET framework's XslCompiledTransform.
Martin Honnen