element-available


This function is used to test whether a particular XSLT instruction or extension element is available for use.

For example, the expression «element-available ('xsl:text') » returns true .

Changes in 2.0

None.

Signature

Argument

Data type

Meaning

name

xs:string

The name of the element being tested . The string must take the form of a QName .

Result

xs:boolean

true if the named element is available for use as an instruction in a template, false otherwise

Effect

The first argument must take the form of a QName : that is, an XML name with an optional namespace prefix that corresponds to a namespace declaration that is in scope at the point in the stylesheet where the element-available() function is called.

If this namespace declaration identifies the XSLT namespace http://www.w3.org/1999/XSL/Transform , then the function returns true if the name is the name of an XSLT-defined instruction, and false otherwise.

The instructions defined in XSLT 1.0 were as follows .

 <xsl:apply-imports> <xsl:apply-templates> <xsl:attribute> <xsl:call-template> <xsl:choose> <xsl:comment> <xsl:copy> <xsl:copy-of> <xsl:element> <xsl:fallback> <xsl:for-each> <xsl:if> <xsl:message> <xsl:number> <xsl:processing-instruction> <xsl:text> <xsl:value-of> <xsl:variable> 

In the XSLT 2.0 specification, several new instructions have been added to this list.

 <xsl:analyze-string> <xsl:document> <xsl:for-each-group> <xsl:next-match> <xsl:perform-sort> <xsl:namespace> <xsl:result-document> <xsl:sequence> 

Instructions are XSLT elements that can appear directly within a sequence constructor. Top-level XSLT declarations such as <xsl:template> and <xsl:key> are not instructions, so in theory they should return false (but don't rely on it: at least one popular processor, Microsoft MSXML3, seems to return true for all XSLT elements). The same applies to elements such as <xsl:param>, <xsl: with-param >, <xsl:sort>, <xsl:when> , and <xsl:otherwise> , that can appear only in specific contexts and not anywhere in a sequence constructor.

If the prefix of the QName identifies any namespace other than the XSLT namespace, then the function returns true if and only if the XSLT processor has an implementation available for the named instruction: that is, if this element can be used as an instruction in a sequence constructor, rather than being treated simply as a literal result element.

Note that the result of the element-available() function does not depend on whether the namespace has been designated as an extension namespace by using the [xsl:]extension-element-prefixes attribute. If the XSLT processor has an implementation of the instruction available, the function should return true whether or not it is currently in a designated extension namespace.

If the QName has no prefix, the default namespace (declared using «xmlns="some.uri" » ) is used. This is one of the few cases where this happens, and the reason is that the name is always an element name: the default namespace applies only to elements.

However, if the QName expands to a name with a null namespace URI, the result of the function will always be false. This is because both XSLT instructions and extension elements will always have a non-null namespace URI.

In principle, you can construct the value of the argument as a runtime expression, rather than supplying it as a string literal. I can't think of any possible reason why it might be useful to do this, but implementers have to allow for the possibility.

Usage and Examples

There are two ways to use this function: it can be used to test for XSLT elements introduced in a later version of XSLT, and it can be used to test for the presence of vendor or third-party extensions.

Testing for Features Available in Later XSLT Versions

The ability to test whether a particular XSLT instruction is available was introduced in XSLT 1.0, but it becomes useful only now that version 2.0 of the specification is available. It was intended to come into its own when later versions of the specification introduced new instructions. As we've seen, the XSLT 2.0 specification introduces several new instructions. If you want to use an instruction such as <xsl:next-match> that became available only in a particular version of XSLT, then you can test to see whether it is available with your chosen XSLT processor before using it. If it is not available, you can either use <xsl:if > to avoid executing it, or use the <xsl:fallback> mechanism to cope with its absence.

So why was the function specified as part of version 1.0? The answer is obvious when you think about it: you want to write a stylesheet that uses version 2.0 features, so you call element-available() in order to fail gracefully if you're running with an XSLT processor that supports version 1.0 features only. However, this will work only if the version 1.0 XSLT processor supports the element-available() function, which is why it was specified from the start. This is an unusually thoughtful piece of forward planning: the XSLT designers didn't want to get into the same kind of forwards-compatibility problems that have bedeviled HTML. Of course, it still means that if you want your stylesheet to run with XSLT processors that support different levels of the language, you will have to write and test conditional code in your stylesheet, but at least the capability is there.

In principle, you can test whether a version 1.0 instruction is available on the basis that there may be subset implementations around; unfortunately , this will work only if the subset implementation includes the element-available() function, which is not guaranteed ; it tends to be one of the things that implementers leave till last.

Note that if you write a stylesheet that uses features in XSLT version 2.0, and if you want to run it with an XSLT 1.0 processor, then you must specify «version="2.0" » on the <xsl:stylesheet> element, or «xsl:version=" 2.0" » on some literal result element, even if you write an <xsl:if > test using element-available() to avoid executing the relevant code. If you specify «version="1.0" » , then any use of new XSLT 2.0 elements is flagged as an error even if the code is never executed.

Here is an example that tests to see whether the new XSLT 2.0 facility to produce multiple output documents is available by testing element-available ('xsl:result-document') . If it isn't available, you can use an alternative approach: for example, you can use the proprietary syntax for this functionality offered by your chosen XSLT 1.0 processor.

Creating Multiple Output Files
start example

This example takes a poem as input, and outputs each stanza to a separate file. A more realistic example would be to split a book into its chapters, but I wanted to keep the files small. The example is written to work with Saxon version 6.x (which implements XSLT 1.0) and also with any processor that conforms to the XSLT 2.0 specification.

Source

The source file is poem.xml . It starts:

  <poem>   <author>Rupert Brooke</author>   <date>1912</date>   <title>Song</title>   <stanza>   <line>And suddenly the wind comes soft,</line>   <line>And Spring is here again;</line>   <line>And the hawthorn quickens with buds of green</line>   <line>And my heart with buds of pain.</line>   </stanza>   <stanza>   <line>My heart all Winter lay so numb,</line>   <line>The earth so dead and frore,</line>   . . .  

Stylesheet

The stylesheet is in file split.xsl . The part to look at is the <xsl:choose> instruction, where each branch calls element-available() to test whether a particular instruction is available, before calling that instruction.

Note that «saxon » is defined as an extension element prefix, so the <saxon:output> element is recognized as an instruction. The <xsl:stylesheet> element specifies «version="2.0 " » so that an XSLT 1.0 processor will not reject <xsl:result-document> as an error.

  <?xml version="1.0"?>   <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   version="2.0">   <xsl:template match="poem">   <poem>   <xsl:copy-of select="title"/>   <xsl:copy-of select="author"/>   <xsl:copy-of select="date"/>   <xsl:apply-templates select="stanza"/>   </poem>   </xsl:template>   <xsl:template match="stanza">   <xsl:variable name="file"   select="concat('verse', string(position()), '.xml')"/>   <verse number="{position()}" href="{$file}"/>   <xsl:choose>   <xsl:when test="element-available('xsl:result-document')">   <xsl:result-document href="{$file}">   <xsl:copy-of select="."/>   </xsl:result-document>   </xsl:when>   <xsl:when test="element-available('saxon:output')"   xmlns:saxon="http://icl.com/saxon">   <saxon:output file="{$file}"   xsl:extension-element-prefixes="saxon">   <xsl:copy-of select="."/>   </saxon:output>   </xsl:when>   <xsl:otherwise>   <xsl:message terminate="yes"   >Cannot write to multiple output files</xsl:message>   </xsl:otherwise>   </xsl:choose>   </xsl:template>   </xsl:stylesheet>  

Output

Provided the stylesheet is run with one of the processors that support the required capability, the principal output file will contain the following skeletal poem (new lines added for legibility).

  <?xml version="1.0" encoding="utf-8" ?>   <poem>   <title>Song</title>   <author>Rupert Brooke</author>   <date>1912</date>   <verse number="1" href="versel.xml"/>   <verse number="2" href="verse2.xml"/>   <verse number="3" href="verse3.xml"/>   </poem>  

Three further output files versel.xml , verse2.xml , and verse3.xml are created in the same directory as this outline. Here is versel.xml :

  <?xml version="1.0" encoding="utf-8" ?>   <stanza>   <line>And suddenly the wind comes soft,</line>   <line>And Spring is here again;</line>   <line>And the hawthorn quickens with buds of green</line>   <line>And my heart with buds of pain.</line>   </stanza>  

To run this using Saxon 7.x (which implements XSLT 2.0), use a command line of the form:

  java-jar c:\MyJava\saxon7.jar -t -o c:\temp\outline.xml poem.xml   split.xsl  

With this command line, the output files will all be written to the directory c:\temp . The <saxon:output> instruction in Saxon 6.x works slightly differently: it will write the files verseN.xml to the current directory, not necessarily to the directory containing the outline.xml file.

end example
 

Note that in this stylesheet, all the information needed to evaluate the <xsl:when> conditions is available at compile time. A good XSLT processor will generate code only for the path that is actually going to be executed.

You can't use element-available() to test whether the XSLT 2.0 element <xsl:import-schema> is available, because this is a declaration rather than an instruction, and a conformant XSLT 2.0 processor should therefore return false (the same result as an XSLT 1.0 processor). If you use this element in an XSLT 1.0 stylesheet, an error will be reported if you specify «version=" 1.0" » on the <xsl:stylesheet> element, but if you specify «version="2.0" » then an XSLT 1.0 processor will ignore the <xsl:import-schema> element, under the rules for forwards-compatible processing. Instead you can test whether the XSLT processor you are using is schema aware using the system-property () function (described on page 581 in this chapter) together with the use-when attribute described in the entry for <xsl:stylesheet> in Chapter 5.

Testing for Vendor Extensions

The second way of using the function is to test for vendor or third-party extensions. If you know that a particular extension instruction is present in some implementations and not others, you can use the element-available() test to see whether it is present, and again use either <xsl:if > or <xsl:fallback> to handle the situation when it isn't.

For example, the Saxon product provides an extension instruction to output an entity reference. This is available under both Saxon 6.x and Saxon 7.x, which use different namespaces and therefore need to be treated as different processors. If you're not using Saxon, you can achieve the same effect by using disable-output-escaping . So to output «&nbsp; » you could write:

  <xsl:choose xmlns:saxon6="http://icl.com/saxon"   xmlns:saxon7="http://saxon.sf.net/">   <xsl:when test="element-available('saxon6:entity-ref')">   <saxon6:entity-ref name="nbsp"   xsl:extension-element-prefixes="saxon6"/>   </xsl:when>   <xsl:when test="element-available('saxon7:entity-ref')">   <saxon7:entity-ref name="nbsp"   xsl:extension-element-prefixes="saxon7" />   </xsl:when>   <xsl:otherwise>   <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>   </xsl:otherwise>   </xsl:choose>  

An alternative to using the element-available() function is to use the <xsl:fallback> mechanism described in Chapter, 3 page 136. An <xsl:fallback> element allows you to define what processing should occur if its containing instruction isn't available. The two mechanisms are essentially equivalent. A possible limitation of <xsl:fallback> is that it can only be used within an element that permits element children: it could not be used, for example, within <xsl:copy-of> as currently defined. However, all the new instructions in XSLT 2.0 have been designed so that <xsl:fallback> can be used as a child element.

See Also

  • function-available() page 564.

  • system-property() page 581.

  • <xsl:fallback> in Chapter 5, page 271.




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