web analytics

Namespaces and XSLT Stylesheets

Options

codeling 1599 - 6654
@2017-09-19 10:18:42

In XML a namespace is a collection of names used for elements and attributes. A URI (usually, a URL) is used to identify a particular collection of names. Instead of including the URI with every element to show which namespace it came from, it's more convenient to name a short abbreviation when a namespace is declared and to then use that abbreviation to identify an element or attribute's namespace. For example, the document element's start-tag in the following stylesheet declares a namespace for the http://www.w3.org/1999/XSL/Transform URI and assigns the prefix xsl to represent it.

  <xsl:stylesheet xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"
     version="1.0">

  <xsl:output method="xml" omit-xml-declaration="yes"/>

  ...

</xsl:stylesheet>

In the above stylesheet, the declaring and referencing of the XSLT namespace xsl is how we tell an XSLT processor which elements and attributes in a stylesheet to treat as XSLT instructions.

@2017-09-19 10:22:38

Namespaces and Your Result Document

What if you want your result document to include elements from a specified namespace? Simply declare and use the namespace you need in your stylesheet and the XSLT processor will

  • put that namespace declaration in the start-tag of the result document's document element, and
  • put the prefix for that namespace in the tags for any result tree elements from that namespace.

For example, to convert the following HTML document to an XLink document, the result needs an XLink namespace declaration and each of the special XLink attributes need a prefix that references that declaration.

<html><body>
<p>The poem's <a href="jmilton.html">author</a> was English.</p>
</body></html>

The stylesheet declares the http://www.w3.org/1999/xlink namespace in the xsl:stylesheet element's start-tag along with the declaration of the http://www.w3.org/ 1999/XSL/Transform namespace.

<xsl:stylesheet xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"
                xmlns:xlink= "http://www.w3.org/1999/xlink"
                version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:template match="a">
  <author xlink:type="simple" xlink:href="{@href}">
    <xsl:apply-templates/></author>
</xsl:template>

<xsl:template match="p">
  <para><xsl:apply-templates/></para>
</xsl:template>

</xsl:stylesheet>

You'll usually find a namespace declaration in a document element's start-tag, and the XSLT processor passes this declaration along to the start-tag of the result document's document element. It also passes all references to that namespace along to the result tree, making the result document a working XLink document.

<para xmlns:xlink= "http://www.w3.org/1999/xlink">
The poem's <author xlink:type="simple" xlink:href="jmilton.html">
author</author> was English.</para>

In XSLT terms, the XSLT processor has added a namespace node to the result tree. (There are six kinds of nodes that may show up in source and result trees: elements, attributes, text nodes, processing instructions, comments, and namespace nodes.) You can prevent this from happening with the xsl:stylesheet element's exclude-result-prefixes attribute. This attribute's name can be confusing, because the namespace prefixes will still show up in the result tree. It doesn't mean "exclude the prefixes in the result"; it means "exclude the namespaces with these prefixes".

For example, the following stylesheet looks just like the one above with the addition of this attribute to tell the XSLT processor to exclude the namespace node represented by the "xlink" prefix. You can list multiple namespace prefixes as the value of the exclude-result-prefixes attribute, as long as they have spaces between them and they're all declared namespaces.


<xsl:stylesheet xmlns:xsl= "http://www.w3.org/1999/XSL/Transform"
                xmlns:xlink= "http://www.w3.org/1999/xlink"
                exclude-result-prefixes="xlink"
                version="1.0">
  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:template match="a">
   <author xlink:type="simple" xlink:href="{@href}">
    <xsl:apply-templates/></author>
  </xsl:template>

  <xsl:template match="p">
   <para><xsl:apply-templates/></para>
  </xsl:template>

</xsl:stylesheet>

Processing the same source document with this stylesheet creates a similar result, except that the document element's start-tag doesn't have the declaration for the XLink namespace:

<para>
The poem's <author xmlns:xlink= "http://www.w3.org/1999/xlink"
xlink:type="simple" xlink:href="jmilton.html">
author</author> was English.</para>

You can also assign result tree elements and attributes to specific namespaces by adding a namespace attribute to the xsl:element instruction or to an xsl:attribute instruction. For example, the second xsl:element instruction in the following template and the two xsl:attribute elements inside of the first xsl:element each include a namespace attribute along with their name attributes. These identify the two namespaces where the element and attribute names belong: the HTML and XLink namespaces.



<xsl:template match="xdata">

  <section>

    <xsl:element name="author">
      <xsl:attribute namespace= "http://www.w3.org/1999/xlink"
        name="type" >simple</xsl:attribute>
      <xsl:attribute namespace= "http://www.w3.org/1999/xlink"
        name="href" >jmilton.html</xsl:attribute>
      John Milton
    </xsl:element>

    <xsl:element name="img" 
      namespace= "http://www.w3.org/TR/REC-html40">
      <xsl:attribute name="src">milton.jpg</xsl:attribute>
    </xsl:element>
    <xsl:apply-templates/>

  </section>

</xsl:template>

When applied to the same source document as the earlier examples, this stylesheet creates a result document that has an author element with two attributes from the XLink namespace and an img element from the HTML namespace. The XSLT processor can make up any namespace prefixes it wants; in this case, they're "ns0" and "ns1".

<section>
<author xmlns:ns0= "http://www.w3.org/1999/xlink" 
        ns0:type="simple" ns0:href="jmilton.html">
      John Milton
    </author>
<ns1:img xmlns:ns1= "http://www.w3.org/TR/REC-html40"
     src="milton.jpg"/>
With Opal Towers and Battlements adorned</section>

To review: the XSLT processor looks through a stylesheet for elements belonging to the XSLT namespace and executes their instructions, and for any elements outside of that namespace (that aren't from a namespace declared for extension elements), it passes them along to the result with namespace declarations if necessary. You can even assign a specific namespace for an element or attribute by adding a namespace attribute to an xsl:element or xsl:attribute element.

@2017-09-19 10:37:34

Using XSLT to Output XSLT

If the elements from the XSLT namespace don't get passed through to the result document, what do you do if you really want XSLT elements in your result element? For example, what if we want to convert the following document to a working XSLT stylesheet?

<ssheet>

  <elementHandler element="para">
    <p><elementContents/></p>
  </elementHandler>

</ssheet>

You use the xsl:namespace-alias element. If you use another temporary namespace (in the example below, "xslAlt") in place of the one you really want (below, "xsl") xsl:namespace-alias lets you tell the XSLT processor to substitute the one you want for the temporary one when it creates the result tree.


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xslAlt="http://www.snee.com/xml/dummy"
     version="1.0">

  <xsl:namespace-alias stylesheet-prefix="xslAlt" 
          result-prefix="xsl"/>

  <xsl:template match="elementHandler">
    <xslAlt:template match="{@element}">
      <xsl:apply-templates/>
    </xslAlt:template>
  </xsl:template>

  <xsl:template match="elementContents">
    <xslAlt:apply-templates/>
  </xsl:template>

  <xsl:template match="ssheet">
    <xslAlt:stylesheet  version="1.0">
      <xsl:apply-templates/>
    </xslAlt:stylesheet>
  </xsl:template>

  <!-- Just copy any other elements, attributes, etc. -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

This stylesheet's first template rule will add an xslAlt:template element to the result tree each time it finds an elementHandler element source tree. Before this template, however, the stylesheet's xsl:namespace-alias instruction tells the XSLT processor to substitute the "xsl" prefix's namespace for the "xslAlt" prefix's namespace in the result document, so the result document is a valid XSLT stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="para">
    <p>
      <xsl:apply-templates />
    </p>
  </xsl:template>
</xsl:stylesheet>

When applied to this source document,

<para>Fallen cherub, to be weak is miserable</para>

the stylesheet created by the transformation with the xsl:namespace-alias element creates this result:

<?xml version="1.0" encoding="UTF-8"?>
<p>Fallen cherub, to be weak is miserable</p>

Creating XSLT instructions in your result document is only the most obvious application of the xsl:namespace-alias element. Whenever you have elements that you don't want recognized as belonging to a certain namespace until later in the process, xsl:namespace-alias can put the prefix you want on those elements. Or, it can take them out -- a result-prefix value of "#default" assigns the relevant result-tree elements to the default namespace, which means they get no namespace prefix at all.

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com