Microsoft XML 2.5 SDK


 

Generating More Sophisticated XML Output

[This is preliminary documentation and subject to change.]

When generating XML, it often is useful to generate comments, processing instructions, and so on. XSL provides a set of commands for creating specific kinds of nodes in the output. Just as the <xsl:attribute> element can insert an attribute into the tree, XSL provides a similar set of elements for inserting other types of nodes. The <xsl:attribute> element is described in Accessing and Outputting Attributes.

The <xsl:comment> element inserts a comment into the output—comments within the style sheet are not passed through to the output, but are treated as comments upon the style sheet itself. When a comment is needed in the output, place the comment text within an <xsl:comment> element.

The <xsl:pi> element allows processing instructions (PIs) to be inserted into the output. The name attribute specifies the name of the attribute, and the content of the element becomes the text of the PI.

The <xsl:element> element provides an alternate mechanism for creating elements in the output. The name attribute specifies the name of the element. The following two ways of creating a DIV element produce identical results.

1) <DIV class="menuItem">
     Choose me
   </DIV>
2) <xsl:element name="DIV">
     <xsl:attribute name="class">menuItem</xsl:attribute>
     Choose me
   </xsl:element>

Note that attributes must be added to elements created using the <xsl:element> element with the <xsl:attribute> element instead of being placed directly on the element.

Since XSL allows output elements to be specified directly, there are only a few rare situations where <xsl:element> is useful. One use is as an escaping mechanism for creating XSL elements in the output, allowing style sheets to generate style sheets.

The following sample converts style sheets to use the <xsl:element> syntax. In the process, it uses the <xsl:element> to generate elements in the XSL namespace and inserts PIs and a comment at the start of the file.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="showxsl.xsl"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
  <xsl:template match="/">
    <xsl:pi name="xml">version="1.0"</xsl:pi>
    <xsl:pi name="xml-stylesheet">type="text/xsl" href="style.xsl"</xsl:pi>
    <xsl:comment>Style sheet converted automatically to &lt;xsl:element&gt; syntax</xsl:comment>
    <xsl:apply-templates select="comment()"/>
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <!-- Copy text, comments and pis -->
  <xsl:template match="comment() | pi() | text()">
    <xsl:copy>
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>
  <!-- Convert non-XSL elements to <xsl:element> syntax -->
  <xsl:template match="*">
    <xsl:element name="xsl:element">
      <xsl:attribute name="name"><xsl:node-name/></xsl:attribute>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
  <!-- Convert non-XSL attribute to <xsl:attribute> syntax -->
  <xsl:template match="@*">
    <xsl:element name="xsl:attribute">
      <xsl:attribute name="name"><xsl:node-name/></xsl:attribute>
      <xsl:value-of/>
    </xsl:element>
  </xsl:template>
  <!-- Copy XSL elements and their attributes -->
  <xsl:template match="xsl:*">
    <xsl:copy>
      <xsl:for-each select="@*">
        <xsl:copy><xsl:value-of/></xsl:copy>
      </xsl:for-each>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

The above style sheet has five templates. The first adds some boilerplate to the root of the output document, and selects all comments and the document element for copying to the output. The second template copies comments, PIs, and text nodes to the output. The third template converts elements to the <xsl:element> syntax. The fourth converts attributes to the <xsl:attribute> syntax. And the final one ensures that any elements from the XSL namespace are copied to the output with their attributes and not converted by the third template.

Using XSL as the Default Namespace

Another use for <xsl:element> is to generate elements when the default namespace of the style sheet is set to XSL. Some style sheets, such as the following one, consist of nearly all elements from the XSL namespace and contain virtually no output elements. It might be convenient to set the default namespace of the document to the XSL namespace, so prefixes can be omitted. <xsl:element> can be used for the rare output elements. Style sheets written in this way can be more readable and compact, and are more amenable to validation with a DTD (Document Type Definition) or XML Schema.

<?xml version="1.0"?>
<stylesheet xmlns="http://www.w3.org/TR/WD-xsl">
  <!-- Identity transformation template -->
  <template>
    <copy>
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </copy>
  </template>
  
  <!-- Rename "stock" elements to "security" -->
  <template match="stock">
    <element name="security">
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </element>
  </template>
</stylesheet>

This sample uses so few named output elements (just one, the "security" element) that it is easier to use the XSL namespace as the default, and use the <xsl:element> element for this one output element. Notice, however, that consistently using the "xsl" prefix helps make your style sheets look familiar to other authors.