6

As I understand from docs, XSLT function document() with empty string as parameter should read current XSLT document. But the following code doesn't work:

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <state>test2</state>
   <xsl:template match="/">
      test1
      <xsl:value-of select="document('')/*/state"/>
    </xsl:template>
   </xsl:stylesheet>

When I apply this XSLT to some XML (just for example), I have only "test1" as output. Why line

 <xsl:value-of select="document('')/*/state"/>

doesn't print "test2"?

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Mikhail
  • 1,583
  • 5
  • 22
  • 34
  • how are you running the transform? –  Jan 27 '11 at 08:46
  • works for me. I get both `test1` and `test2` when running through Eclipse XSL Transformer. – dogbane Jan 27 '11 at 08:49
  • 1
    if you're using the MSXML library on Windows, you may need to enable the use of the document function: `styledocument.setProperty("AllowDocumentFunction", true);` see http://msdn.microsoft.com/en-us/library/ms256465.aspx –  Jan 27 '11 at 08:57
  • I use xalan that is a part of java 6 – Mikhail Jan 27 '11 at 08:59
  • Any attempt of running that stylesheet should result in some **error message** like *"Child elements of xsl:stylesheet must be bound to a namespace"* –  Jan 27 '11 at 17:26

2 Answers2

14

The definition of document('') is that it reads the XML document whose URI is the same as the base URI of the instruction in the stylesheet containing the document('') call. Unless you use external entities, this is normally the same as the base URI of the stylesheet module. If it doesn't work, this is often because the base URI of the stylesheet module is unknown. This can easily happen if the XSLT processor is given a stylesheet that's in memory (for example as a character string or a DOM) rather than a resource retrieved via a URI. For example, if you use a JAXP StreamSource and don't call setSystemId() then the base URI will be unknown.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • +1 Good answer. In addition, there are some enviroments where the `document()` function could be not allowed for some privilege level. –  Jan 27 '11 at 17:44
1

You should declare your own namespace, like this:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="http://localhost"
    exclude-result-prefixes="my">
    <xsl:output method="text"/>

    <my:state>test2</my:state>

    <xsl:template match="/">
        <xsl:text>test1</xsl:text>
        <xsl:value-of select="document('')/*/my:state"/>
    </xsl:template>
</xsl:stylesheet>

Ouput:

test1test2

Quoting Michael Kay:

A user-defined top-level element must also belong to a namespace with a non-null URI, different from the XSLT namespace, and preferably different from the namespace URI used by any vendor. These elements are ignored by the XSLT processor.

Flack
  • 5,862
  • 2
  • 23
  • 27
  • still doesn't work in Java 6 (uses xalan). But anyway thanks, it seems that used version of XSL processor requires some special syntax – Mikhail Jan 27 '11 at 10:36
  • 1
    +1 For syntax error. Also, you could quote the [specs](http://www.w3.org/TR/xslt#stylesheet-element): *"In addition, the `xsl:stylesheet` element may contain any element not from the XSLT namespace, provided that the expanded-name of the element has a non-null namespace URI."* –  Jan 27 '11 at 17:30