Menu

#41 The document('') function should reference the XSLT itself.

open
nobody
5
2014-08-17
2006-07-05
Doug Domeny
No

In IE 6.0, the document('') function references the
web page that includes Sarissa.

In FireFox 1.0, the document('') function references
the source XML document.

Discussion

  • Emmanuil Batsis (Manos)

    Logged In: YES
    user_id=542984

    hey Doug, are you using xsl:include or xsl:import?

     
  • Doug Domeny

    Doug Domeny - 2006-10-30

    Logged In: YES
    user_id=1545119

    Neither xsl:include nor xsl:import are used. A snippet of the XSLT is shown below. In IE 6 on WinXPSP2, the tag
    name display is 'html' (and only because the web page is well-formed otherwise an error would occur). The
    xsl:variable shows how I'm trying to use document(''). In practice the XSLT is constructed as a JavaScript string.

    Thank you for your response.

    <?xml version='1.0'?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="ektdesign"
    xmlns:ektdesign="urn:ektdesign">
    <xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
    <ektdesign:datalist>
    <option>test</option>
    </ektdesign:datalist>
    <xsl:variable name="oldDataList" select="document('')/xsl:stylesheet/ektdesign:datalist"/>
    <xsl:template match="select">
    <select>
    <option><xsl:value-of select="name(document('')/*[1])" /></option>
    </select>
    </xsl:template>
    :
    </xsl:stylesheet>

     
  • Emmanuil Batsis (Manos)

    Logged In: YES
    user_id=542984

    According to the rec, document("") refers to the root node
    of the stylesheet so this an MSXML bug. Just to make sure
    this is not my bad, have you tried scripting the
    transformation with native MSXML APIs (i.e. without sarissa)?

     
  • Doug Domeny

    Doug Domeny - 2006-10-30

    Logged In: YES
    user_id=1545119

    Yes, I originally developed on IE and ported it to Sarissa. The
    original IE code was xmlDoc.transformNode(xsltDoc), so it didn't use
    createProcessor. It was a fairly easy port and most of it works fine
    on both IE and FF. You've done a good job making it cross-browser. I
    hope there is just some context property that needs to be set in the
    transform object that is incorrect for both browsers. In .NET a
    UrlResolver required when the XSLT is a string instead of a file.
    The problem, although different, also happens with Mozilla FireFox.

     
  • Emmanuil Batsis (Manos)

    Logged In: YES
    user_id=542984

    I think i know what is wrong. In IE, i serialise the XSLT to
    make it a freethreaded/template combo, so it misses the
    context info.

    Maybe if the XSLT loaded had an xml:base attribute [1]?

    [1] http://www.w3.org/TR/xmlbase/#syntax

     
  • Doug Domeny

    Doug Domeny - 2006-10-31

    Logged In: YES
    user_id=1545119

    The XSLT is originally a string, so I don't think xml:base will help. And neither Firefox nor IE works correctly,
    so it wouldn't be just something with how IE is handled.
    Shown here is the code I use to transform:

    var xmlDoc = Sarissa.getDomDocument();
    xmlDoc.async = false;
    xmlDoc = (new DOMParser()).parseFromString(xml, "text/xml");

    var xsltDoc = Sarissa.getDomDocument();
    xsltDoc.async = false;
    xsltDoc = (new DOMParser()).parseFromString(xslt, "text/xml");

    var processor = new XSLTProcessor();
    processor.importStylesheet(xsltDoc);
    var newDoc = processor.transformToDocument(xmlDoc);

     
  • Nobody/Anonymous

    Logged In: NO

    If this is MSXML 6.0 the document() function now works on CVS.

     
  • Doug Domeny

    Doug Domeny - 2007-04-23

    Logged In: YES
    user_id=1545119
    Originator: YES

    The AllowDocumentFunction property is now set for MSXML 6.0, but the original problem remains. The document('') function does not reference the XSLT document itself when the XSLT is a string rather than a URL. IE references the web page. FireFox references the XML document.

     
  • Nobody/Anonymous

    Logged In: NO

    Hmm. This comes to choosing between the ability to get/set parameters ( i need to re-parse the stylesheet for the threaded doc) and keeping the url. That last property is read only i think.

     
  • Doug Domeny

    Doug Domeny - 2007-04-23

    Logged In: YES
    user_id=1545119
    Originator: YES

    Actually, in my case, the XSLT is originally a string, not a URL, so it's not a matter of keeping the URL.

    I was thinking, in those cases where the XSLT is a URL, to have a separate method to load the XSLT URL using the FreeThreadedDOMDocument object to avoid having to load the XSLT twice.

     
  • Doug Domeny

    Doug Domeny - 2007-04-26

    Logged In: YES
    user_id=1545119
    Originator: YES

    In working with both Microsoft and Mozilla, they have acknowledged the problem. There is some debate as to whether document('') should refer to the web page when the XSLT is a string because the string does not have a URI and therefore it defaults back to the web page. Since it is important for an XSLT to reference itself (and not the web page it might be in), IMHO, it document('') should consistently reference the XSLT regardless of whether the XSLT is a string or URL.

    However, in regard to Sarissa, the problem is broadly exposed by serializing the XSLT as a string and loading it into FreeThreadedDOMDocument. I thought of adding a Sarissa.getXsltDocument method that would use FreeThreadedDOMDocument and therefore not need to reload the XSLT in XSLTProcessor.prototype.importStylesheet.

    Any thoughts?

     
  • Nobody/Anonymous

    Logged In: NO

    I'm a bit dizzy right now, how can we make this work for both IE and browsers implementing Mozilla's XSLTProcessor?

    Many thanks,

    Manos

     
  • Doug Domeny

    Doug Domeny - 2007-04-26

    Logged In: YES
    user_id=1545119
    Originator: YES

    As a workaround, Jonas Sicking writes, "One way of doing so would be to use .setParameter to pass the DOM of the stylesheet as a parameter and then refer to the stylesheet through that parameter." - http://groups.google.com/group/mozilla.dev.tech.xslt on thread "problem self-referencing using document('') to reference parameters" dated Apr 25, 6:17 pm

    If I come up with a working solution, I'll post it here. I don't think there is one for Mozilla, but I'll try creating a separate method to create an XsltDocument using FreeThreadedDOMDocument in IE to at least reduce probably of encountering the problem.

     
  • Doug Domeny

    Doug Domeny - 2007-04-30

    Logged In: YES
    user_id=1545119
    Originator: YES

    This seems to work. There is a new method getXsltDocument, similar to getDomDocument, but for XSLTs. Also affected is .importStylesheet (for IE). There are three places where getDomDocument is defined other than for IE that need the following line:
    Sarissa.getXsltDocument = Sarissa.getDomDocument;

    I've tested on IE 7/Windows and FireFox 2.0/Windows.

    Sarissa.getXsltDocument = function(sUri, sName){
    if(!_SARISSA_THREADEDDOM_PROGID){
    _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.5.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
    };
    var oDoc = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
    Sarissa.setXpathNamespaces(oDoc, "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
    oDoc.resolveExternals = true; // MSXML 2.0 and later
    if ("MSXML2.FreeThreadedDOMDocument.6.0" == _SARISSA_THREADEDDOM_PROGID) {
    oDoc.setProperty("AllowDocumentFunction", true); // This property is supported in MSXML 3.0 SP4, 4.0 SP2, 5.0, and 6.0. The default value is true for 3.0, 4.0, and 5.0. The default value is false for 6.0.
    oDoc.setProperty("AllowXsltScript", true); // This property is supported in MSXML 3.0 SP8, 5.0 SP2, and 6.0. The default value is true for 3.0 and 5.0. The default value is false for 6.0.
    oDoc.setProperty("ProhibitDTD", false); // This property is supported in MSXML 3.0 SP5, 4.0 SP3, 5.0 SP2, and 6.0. The default value is false for 3.0, 4.0, and 5.0. The default value is true for 6.0.
    }
    // if a root tag name was provided, we need to load it in the DOM object
    if (sName){
    // create an artifical namespace prefix
    // or reuse existing prefix if applicable
    var prefix = "";
    if(sUri){
    if(sName.indexOf(":") > 1){
    prefix = sName.substring(0, sName.indexOf(":"));
    sName = sName.substring(sName.indexOf(":")+1);
    }else{
    prefix = "a" + (_sarissa_iNsCounter++);
    };
    };
    // use namespaces if a namespace URI exists
    if(sUri){
    oDoc.loadXML('<' + prefix+':'+sName + " xmlns:" + prefix + "=\"" + sUri + "\"" + " />");
    } else {
    oDoc.loadXML('<' + sName + " />");
    };
    };
    return oDoc;
    };

    XSLTProcessor.prototype.importStylesheet = function(xslDoc){
    if(!_SARISSA_THREADEDDOM_PROGID){
    _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
    };
    xslDoc.setProperty("SelectionLanguage", "XPath");
    xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
    // convert stylesheet to free threaded
    var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
    // make included/imported stylesheets work if exist and xsl was originally loaded from url
    if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
    converted.async = false;
    if (_SARISSA_THREADEDDOM_PROGID == "MSXML2.FreeThreadedDOMDocument.6.0") {
    converted.setProperty("AllowDocumentFunction", true);
    converted.resolveExternals = true;
    }
    converted.load(xslDoc.url);
    } else {
    converted.loadXML(xslDoc.xml);
    };
    converted.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
    var output = converted.selectSingleNode("//xsl:output");
    this.outputMethod = output ? output.getAttribute("method") : "html";
    this.template.stylesheet = converted;
    this.processor = this.template.createProcessor();
    // for getParameter and clearParameters
    this.paramsSet = new Array();
    };

     

Log in to post a comment.

MongoDB Logo MongoDB