When passed a URI containing a fragment identifier ("doc#bla"), the
document() function should interpret it according to the document's
ID table, which can be accessed using the id() function.

# more /t2 document-function-fragment-id.xml
<!DOCTYPE Boote [
<!ATTLIST Boot id ID #IMPLIED>
]>
<Boote>
  <Boot id="U3"/>
  <Boot/>
  <Boot id="U5"/>
  <Boot id="U99"/>
</Boote>

# more /t2 document-function-fragment-id.xsl
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

  <xsl:variable name="doc"
    select="'document-function-fragment-id.xml'"/>
  <xsl:variable name="id" select="'U5'"/>

  <xsl:template match="/">
    <xsl:copy-of select="document( concat( $doc, '#', $id))"/>
    <!-- Only in 2.0:
    <xsl:copy-of select="document( $doc)/id( $id)"/>
    <xsl:copy-of select="id( $id, document( $doc))"/>
    -->
  </xsl:template>
</xsl:stylesheet>

Saxon (6.5, 9.1) and LibXSLT (1.1.24) produce the following result:

  <Boot id="U5"/>

Xalan 2.7.1 disregards the fragment identifier and copies the entire
document instead of doing a lookup using the document's ID table.

The XSLT 1.0 specification says:

  If the URI reference does contain a fragment identifier, the function
  returns a node-set containing the nodes in the tree identified by the
  fragment identifier of the URI reference. The semantics of the
  fragment identifier is dependent on the media type of the result of
  retrieving the URI. If there is an error in processing the fragment
  identifier, the XSLT processor may signal the error; if it does not
  signal the error, it must recover by returning an empty node-set.
  -- http://www.w3.org/TR/1999/REC-xslt-19991116#document

  <xsl:variable name="id" select="document('lookup.xml#ML1971HH')"/>

This feature of looking up an ID in an external document by specifying
it in the fragment identifier is really convenient. Where it is not
supported, you have to do a context switch using <xsl:for-each> and
create a result tree fragment (RTF) and then possibly use x:node-set(),
which is inconvenient:

  <xsl:variable name="node-with-id"><!-- RTF in XSLT 1.0 -->
    <xsl:for-each select="document('lookup.xml')">
      <xsl:copy-of select="id('ML1971HH')"/>
    </xsl:for-each>
  </xsl:variable>
  <xsl:copy-of select="$node-with-id"/>
  <StrVal><xsl:value-of select="$node-with-id"/></StrVal>
  <!-- Have to use exsl:node-set() to navigate the RTF. -->

This caught my attention here:

Re: [xsl] AltovaXML and fragment identifier - Michael Ludwig
http://markmail.org/message/6ad5trhfztlzior7

Michael Ludwig

Reply via email to