It's really up to the JAXP specification for the URIResolver to say what happens. But of course JAXP currently doesn't cover XSLT 2.0 at all - and its past track record is that when JAXP and Xalan differ, JAXP often changes to match the Xalan behavior.
 
DOM users, I think, often use the document element as a surrogate for the document itself. That's the convention Saxon is assuming in this case.
 
Michael Kay
http://www.saxonica.com/


From: saxon-help-admin@lists.sourceforge.net [mailto:saxon-help-admin@lists.sourceforge.net] On Behalf Of Steven Grossman
Sent: 18 May 2006 16:41
To: saxon-help@lists.sourceforge.net
Subject: [saxon] RE: URIResolver returns entire document instead of a subtree

Michael,
 
Thanks for the response.  The following DOMSource does indeed return the desired result.
 
    Document newDocument = documentBuilder.newDocument();
    childNode = newDocument.importNode(childNode, true);
    newDocument.appendChild(childNode);
    return new DOMSource(newDocument);
 
The spec does say that a document node is returned.  It's less clear in describing what happens if the URI retrieves something other than a document node.  If this is considered a lack of a mapping, the Xpath spec suggests an appropriate error.  However, it leaves room for implementations to do as they please.  The XSLT spec doesn't seem to address this scenario.
 
I would expect 1 of 2 implementations when an API encounters a node other than a document node.  Choice one is to marshal it into a document node(MATSUHASHI,kazuaki points out that this is what Xalan does).  Choice 2 is to throw an exception.
Saxon seems to have taken an approach similar to the one described in the xslt spec regarding optional recovery from a fragment identifier error - it returns the parent document node.  I feel that this approach is error prone - chances are that the returned document node is not expected and cannot be handled properly by the stylesheet.
 
Thoughts?
 
Steven
 
-----------
 
 From: Michael Kay mike@sa...
 RE: URIResolver returns entire document instead of a subtree
 2006-05-17 04:57
 
 
 The spec of the document() function in XSLT 2.0 implies that if the URI
 contains no fragment identifier, the result will always be a document node.
 Without this rule, it's very hard to achieve repeatability of results (two
 calls on document() with the same arguments must return the same results).
 
 You could write your own extension function to return an element node in the
 document, or you could copy the subtree and return the copy.
 
 Michael Kay
 http://www.saxonica.com/
 
 
   _____ 
 
 From: saxon-help-admin@li...
 [mailto:saxon-help-admin@li...] On Behalf Of Steven Grossman
 Sent: 16 May 2006 22:22
 To: saxon-help@li...
 Subject: [saxon] URIResolver returns entire document instead of a subtree
 
 
 I've implemented a URIResolver that returns subtrees of existing documents.
 I've noticed that Saxon is passing the entire document instead of my
 subtrees.  Here's the source code:
 
 
 import java.io.StringReader;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Source;
 import javax.xml.transform.Templates;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.URIResolver;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
 public final class URIResolverProblem {
     private static String XSLT =
             "<xsl:stylesheet version=\"2.0\"
 xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"
 <http://www.w3.org/1999/XSL/Transform\> >\n" +
             "    <xsl:output indent=\"yes\" />\n" +
             "    <xsl:strip-space elements=\"*\"/>\n" +
             "\n" +
             "    <xsl:template match=\"/\">\n" +
             "        <xsl:copy-of select=\"document('any.uri')\"/>\n" +
             "    </xsl:template>\n" +
             "</xsl:stylesheet>";
 
     private static final String XML = "<root><leaf/></root>";
 
     public static void main(String[] args) throws TransformerException,
 ParserConfigurationException {
         TransformerFactory tfactory = TransformerFactory.newInstance();
         DocumentBuilder documentBuilder =
 DocumentBuilderFactory.newInstance().newDocumentBuilder();
         tfactory.setURIResolver(new SampleResolver());
         Templates stylesheet = tfactory.newTemplates(new StreamSource(new
 StringReader(XSLT)));
         Transformer transformer = stylesheet.newTransformer();
         DOMSource emptySource = new
 DOMSource(documentBuilder.newDocument());
         transformer.transform(emptySource, new StreamResult(System.out));
     }
 
     private static class SampleResolver implements URIResolver {
         private final DocumentBuilder documentBuilder;
         public SampleResolver() throws ParserConfigurationException {
             this.documentBuilder =
 DocumentBuilderFactory.newInstance().newDocumentBuilder();
         }
 
         public Source resolve(String href, String base) throws
 TransformerException {
             // for simplicity, ignoring href
             try {
                 Document document = documentBuilder.parse(new
 InputSource(new StringReader(XML)));
                 NodeList childNodes =
 document.getDocumentElement().getChildNodes();
                 for (int i = childNodes.getLength() - 1; i >= 0; i--) {
                     Node childNode = childNodes.item(i);
                     if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                         System.out.println("\nreturning the following node:
 " + childNode.getNodeName() + "\n");
                         return new DOMSource(childNode);
                     }
                 }
             } catch (Exception e) {
                 throw new TransformerException(e);
             }
             throw new TransformerException("could not find element");
         }
     }
 }
 
 here's the output:
 
 returning the following node: leaf
 
 <?xml version="1.0" encoding="UTF-8"?>
 <root>
    <leaf/>
 </root>
 
 So, I'm returning a DOMSource consisting of the 'leaf' node, but saxon
 returns the 'root' node.
 
 Any ideas?
 
 Steven
 


Love cheap thrills? Enjoy PC-to-Phone calls to 30+ countries for just 2/min with Yahoo! Messenger with Voice.