xsl:text


The <xsl:text> instruction is used within a sequence constructor to output literal text to the result sequence. The purpose of wrapping an <xsl:text> element around literal text is to ensure that whitespace is preserved.

Changes in 2.0

None.

Format

 <xsl:text   disable-output-escaping? = "yes"  "no">   <!-- Content: character data --> </xsl:text> 

Position

<xsl:text> is an instruction. It is always used as part of a sequence constructor.

Attributes

Name

Value

Meaning

disable-output-escaping

optional

«yes » «no »

The value «yes » indicates that special characters in the output (such as «< » ) should be output as is, rather than using an XML escape form such as «&lt; ». The default value is «no »

Content

A text node. The element may also be empty. It must not contain other elements such as <xsl:value-of> .

Effect

Text appearing within a sequence constructor in the stylesheet is copied to the result sequence (in the form of a new text node) whether it is enclosed by <xsl:text> or not. The only direct effect of enclosing text in an <xsl:text> element is that the handling of whitespace is different. A whitespace node appearing in the stylesheet (that is, a text node that consists only of whitespace) is copied to the result tree only if:

  • it appears within an <xsl:text> element, or

  • an enclosing element has the attribute «xml:space="preserve" », and this is not overridden by an inner enclosing element specifying «xml:space="default" »

The disable-output-escaping attribute controls whether special characters such as «< » should be escaped (that is, converted to a character reference or entity reference such as «&lt; » ) if they appear in the text. The default value is «no » . The value «yes » may be ignored under some circumstances, for example if the result of the transformation is written to a DOM rather than being serialized as an XML file.

Usage

There are two main reasons for using <xsl:text>, which are to control the output of whitespace, and to disable the escaping of special characters by the serializer. These are discussed in the next two sections.

Whitespace Control

The most obvious case where <xsl:text> is useful is to force output of whitespace. An example is given in the XSLT specification. If you write:

  <xsl:value-of select="first-name"/> <xsl:value-of select="last-name"/>  

the space between the first name and the last name will be lost, because it is part of a node that contains whitespace only (a single space character). To force a space to appear between the first name and the last name, write:

  <xsl:value-of select="first-name"/>   <xsl:text> </xsl:text>   <xsl:value-of select="last-name"/>  

The arrangement on three lines here is purely for readability, but it does not affect the output, because the newline characters are now in whitespace-only nodes that will not be output.

If you find this long-winded, another way of achieving the same effect is to write:

  <xsl:value-of select="first-name, last-name" separator=" "/>  

The other aspect of the problem is to prevent the output of unwanted whitespace. Fortunately in HTML output extra whitespace usually doesn't matter, because the browser will ignore it. For XML or text output, however, avoiding unwanted whitespace can be important.

If you are suffering from excess whitespace in your output, the first thing to establish is whether it comes from the source document or from the stylesheet. If the whitespace is adjacent to text copied from the source document, then it probably comes from the source document; but if it is adjacent to text that appears in the stylesheet, then this is the most likely source. Check also that the unwanted whitespace isn't coming from the serializer, by setting <xsl:output indent="no"/> .

If the unwanted whitespace comes from the source document, consider using <xsl: strip-space > to remove nodes consisting entirely of whitespace, or the normalize-space() function to remove leading and trailing spaces around visible text.

The <xsl:text> element can be used to suppress unwanted whitespace that originates in the stylesheet. For example, consider the following template:

  <xsl:template match="stage-direction">   [ <xsl:value-of select="."/> ]   </xsl:template>  

The intention here is to output a stage direction enclosed in square brackets. But the text nodes containing the opening and closing square brackets also contain a newline character and several spaces, which will be written to the output destination along with the brackets themselves . To prevent this behavior, the simplest way is to use empty <xsl:text> elements before and after, thus:

  <xsl:template match="stage-direction">   <xsl:text/>[ <xsl:value-of select="."/> ]<xsl:text/>   </xsl:template>  

The effect of this is that the extra newlines and spaces now belong to whitespace-only nodes, which are stripped from the stylesheet and ignored.

Note that it is incorrect to use an <xsl:text> element around the <xsl:value-of> element, as <xsl:text> elements must contain text data only. So the following is wrong:

  <!-- WRONG -->   <xsl:text>[ <xsl:value-of select="."/> ]</xsl:text>   <!-- WRONG -->  

Controlling Output Escaping

Normally, when you try to output a special character such as «< » or «& » in a text node, the special character will be escaped in the output file using the normal XML escaping mechanisms. The escaping is done by the serializer: The text node written in the result tree contains a «< » or «& » character, and the serializer translates this into «&lt; » or «&amp; » . The serializer is free to represent the special characters any way it wants, for example it can write «< » as «&lt; » , «&#60; » , or «<![CDATA[<]]> » , because these are all equivalent according to the XML standard. The one thing it will not write is «< » . So, it doesn't matter how you write the «< » in your input: The serializer sees a «< » and escapes it in the output.

There are several valid reasons why you might not want this behavior. For example:

  • The output is not XML or HTML at all; it is (say) a data file in comma-separated-values format.

  • The output is HTML and you want to exploit one of the many HTML quirks where special characters are needed without escaping, for example a «< » sign in a piece of client-side JavaScript on your HTML page.

  • The output is XML and you want to achieve some special effect that the XSLT processor won't let you do, for example to output an entity reference such as «& current-date ; » or a document type declaration containing an entity declaration.

  • The output is some format that uses angle- bracket syntax but is not pure XML or HTML; for example, ASP pages or Java Server Pages, which both use «<% » and «%> » as delimiters. (If you are generating Java Server Pages, note that these have an alternative syntax that is pure XML; however, this is not widely used.)

If the output is not XML or HTML at all, then rather than using disable-output-escaping it is better to set «method="text" » on the <xsl:output> element.

The use of disable-output-escaping is often discouraged; indeed it is officially deprecated in XSLT 2.0. The underlying reason for this is that it works only if the result tree is being serialized. If the result tree is fed directly into another application, then disable-output-escaping has no effect. This happens, for example, in the Netscape browser, where the HTML-structured result tree is used directly by the rendering engine, without first serializing it as text and then re-parsing it. So a stylesheet that depends on disable-output-escaping won't always work.

The second reason that the facility is discouraged is that it's often a symptom of careless programming: Its use reveals that the stylesheet author is thinking too much in terms of creating tags in a serialized file, not in terms of creating nodes in a result tree.

Here's an example of a misuse of disabling output escaping that you will often encounter (only in other people's stylesheets, of course). The author wanted to get markup tags into the output document, and they couldn't see how to achieve this with the regular facilities of <xsl:element> or literal result elements. For example, the author might have been thinking along these lines:

  <!-- WRONG -->   <xsl:template match="bullet"/>   <xsl:if test='not(preceding::*[1][self::bullet])">   <ul>   </xsl:if>   <li><xsl:value-of select="."/></li>   <xsl:if test='not(following::*[1][self::bullet])'>   </ul>   </xsl:if>   </xsl:template>   <!-- WRONG -->  

The intended effect here is to output a <ul> tag if the preceding element is not a bullet element, and to output a </ul> tag when the following element is not a bullet element. Of course it doesn't work, because the <ul> and </ul> tags are not properly nested: This template will be thrown out by the XML parser before the XSLT processor even gets to look at it.

So their next thought might be to write the tags as text, as follows :

  <xsl:template match="bullet"/>   <xsl:if test='not(preceding::*[self::list-item])'>   <xsl:text disable-output-escaping="yes">&lt;ul&gt;</xsl:text>   </xsl:if>   <li><xsl:value-of select="."/></li>   <xsl:if test='not(following::*[self::list-item])'>   <xsl:text disable-output-escaping="yes">/&lt;ul&gt;</xsl:text>   </xsl:if>   </xsl:template>  

You now have something that is legal XML and indeed legal XSLT, but it's not guaranteed to work under all circumstances. And even if it does work, it's badly written code, because it's cutting against the grain of the language.

With a bit of thought you can usually find a way to achieve the output you want without resorting to such devices.

The first thing is to think in terms of outputting a result tree containing nodes, not a text file containing tags. Don't try to generate the <ul> start tag and the </ul> end tag as two separate actions; try to generate a <ul> element node as a single action, and then generate its children.

In fact, when you see this kind of logic, you can be pretty sure that the problem being tackled is a grouping problem. The solution to a grouping problem always involves two nested loops : In this case an outer loop to generate the <ul> element, and an inner loop to generate the <li> elements. The solution to this particular grouping problem is shown as the first example of how to use the group -adjacent attribute of <xsl:for-each-group> , on page 281.

Examples

Here are two simple examples using <xsl:text> to control the output of whitespace:

  1. Output first-name and last-name, separated by a space:

      <xsl:value-of select="first-name"/>   <xsl:text> </xsl:text>   <xsl:value-of select-"last-name"/>  

    Another way to achieve the same effect is to use the concat() function:

      <xsl:value-of select="concat(first-name,' ', last-name)"/>  
  2. Output a comma-separated list of values:

      <xsl:output method="text"/>   <xsl:template match="book">   <xsl:value-of select="title"/>,<xsl:text/>   <xsl:value-of select="author"/>,<xsl:text/>   <xsl:value-of select="price"/>,<xsl:text/>   <xsl:value-of select="isbn"/><xsl:text>   </xsl:text>   </xsl:template>  

    The purpose of the empty <xsl:text/> elements is to split the comma and the following newline character into separate text nodes; this ensures that the newline character becomes part of a whitespace-only node, and is therefore not copied to the output. The final <xsl:text> element ensures that a newline is written at the end of each record.

    Another way to achieve this is with the separator attribute of <xsl:value-of> :

      <xsl:value-of select="title, author, price, isbn" separator=","/>  

The following example is code that you might see used to output an «&nbsp; » entity reference:

  <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>  

Note that outputting a #xa0 (or #160 ) character will generally have exactly the same effect, to do this you can simply write:

  <xsl:text>&#xA0;</xsl:text>  

Rather than use disable-output-escaping in this situation, which will produce an incorrect result if the result tree is not serialized, a better solution is to use character maps. Output the non-breaking-space character as «#xa0; » , and then ask for it to be serialized as «&nbsp; » by defining the character map:

  <xsl:character-map name="nbsp">   <xsl:output-character character="&#xA0;" string="&amp;nbsp;"/>   </xsl:character-map>  

The character map must then be referenced by specifying:

  <xsl:output use-character-maps="nbsp"/>  

See Also

  • <xsl:character-map> on page 229

  • <xsl:value-of> on this page 465




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net