How Do You Output Plain Text in XSLT?

Generating plain text rather than XML or HTML in XSLT is achieved using the top-level <xsl:output> declaration configured with method="text". This guide details the essential syntax, configuration attributes, whitespace management techniques, and practical examples required to transform XML source documents into formats such as CSV, TSV, or custom unformatted text files.

The <xsl:output> Text Declaration

To switch the transformation processor from generating markup trees to serializing raw character data, declare <xsl:output method="text"/> as a direct child of the root <xsl:stylesheet> element.

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

  <xsl:template match="/">
    <!-- Plain text output rules go here -->
  </xsl:template>

</xsl:stylesheet>

When method="text" is specified:

Key Attributes for Text Output

The <xsl:output> element supports several optional attributes that refine how plain text is encoded and processed:

<xsl:output 
    method="text" 
    encoding="UTF-8" 
    media-type="text/plain" 
    omit-xml-declaration="yes" />

Managing Spacing, Delimiters, and Line Breaks

Because plain text depends entirely on exact spacing and line delimiters rather than markup elements, controlling whitespace is essential.

Explicit Text with <xsl:text>

To output precise spaces, commas, tabs, or static labels without the stylesheet processor stripping them away, wrap the content in <xsl:text> elements:

<xsl:value-of select="firstName" />
<xsl:text>, </xsl:text>
<xsl:value-of select="lastName" />

Inserting Newlines

Line feeds can be introduced using the standard XML character reference &#10; (LF) or &#13;&#10; (CRLF):

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

Complete Transformation Example

Consider this XML dataset representing a list of employees:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
  <employee>
    <id>101</id>
    <name>Jane Doe</name>
    <role>Engineer</role>
  </employee>
  <employee>
    <id>102</id>
    <name>John Smith</name>
    <role>Designer</role>
  </employee>
</employees>

The following XSLT stylesheet uses method="text" to convert the XML into a CSV file:

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

  <xsl:template match="/employees">
    <!-- CSV Header -->
    <xsl:text>ID,Name,Role&#10;</xsl:text>
    
    <!-- CSV Rows -->
    <xsl:for-each select="employee">
      <xsl:value-of select="id" />
      <xsl:text>,</xsl:text>
      <xsl:value-of select="name" />
      <xsl:text>,</xsl:text>
      <xsl:value-of select="role" />
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

The resulting output is clean, unescaped text:

ID,Name,Role
101,Jane Doe,Engineer
102,John Smith,Designer