Skip to content

How to use xmldom in non node.js JavaScript platforms like Rhino or SpiderMonkey

Mads Bondo Dydensborg edited this page May 13, 2014 · 1 revision

Background

The current code base of xmldom requires you to encapsulate each file when loading it. This is done automatically by node.js, but, AFAIK, not by browsers or many other (homerolled) JavaScript environments.

At least one reason you need to do this, is because both the file dom-parser.js and the file sax.js, defines a global (toplevel) function called appendElement. So, no matter what order you load the files in, one or the other declaration will be overriden. This will give problems, such as:

error "end tag name: root is not match the current start tagName:undefined"

You can solve this by implementing support for nodejs's 'require' function in your environment. However, this may not be easily done in your specific setting.

Another solution is to load each file into a seperate object, and only export the symbols that would be exported by the node js module system normally. You will need a "load" function (or similar), that can load a file into a specific object (normally the Global object, but here something else). When you have that, you can use code like this to emulate the behaviour of node.js (poor mans version):

var XMLDOM = function() {
    
    // LoadObject does the actual loading of files. It takes two arguments. 
    // The first argument is an object to use as root object for the loading of the file
    // The second is the filename
    // Your environment must supply this, or something similar.

    // I think order of loading may matter, btw.

    // Main entry point is dom-parser.js
    var dpObj = {};
    loadObject ( dpObj, "dom-parser.js" );
    var dp_exports = {};

    // Simulate require part of dom-parser.js

    // First, sax
    var saxObj = {};
    loadObject( saxObj, "sax.js" );
    // This is the exports from sax
    var sax_exports = { XMLReader : saxObj.XMLReader };
    dpObj.XMLReader = sax_exports.XMLReader;

    // Now, dom
    var domObj = {};
    loadObject( domObj, "dom.js" );
    var dom_exports = { DOMImplementation : domObj.DOMImplementation, 
                        XMLSerializer : domObj.XMLSerializer };

    // And, the rest of the dom-parser require stuff
    dpObj.DOMImplementation = dp_exports.DOMImplementation = dom_exports.DOMImplementation;
    dp_exports.XMLSerializer = dom_exports.XMLSerializer;
    dp_exports.DOMParser = dpObj.DOMParser;

    return dp_exports;
}();

After that, you can run code like this:

// Some test functions
function test1() {
    var doc = new XMLDOM.DOMParser({
      errorHandler:function(key,msg){
          console.error(key, msg);
          throw new Error( "key : " + key + "\nmsg: " + msg );
      }
    }).parseFromString('<some>xml</some>', 'text/xml');
    return doc;
}

and it will work.