Grauw’s blog

I was browsing around the net looking for an example of DOM3 Load and Save in ECMAScript (aka JavaScript), but I wasn’t really able to find one. So, I had to find out the gory details myself by delving through the specification -_-;;.

From the results of that research, I put together a little example.

» Take a look at the DOM3 L&S example

It currently only works in the Opera browser (Mozilla support is still in progress), but not perfectly yet. To be more specific, I’ve found a number of bugs in Opera’s implementation:

  • Unprefixed attributes are parsed incorrectly on prefixed element (e.g. <b:border class="xxx"> is turned into <b:border b:class="xxx">)
  • Browser crashes when parsing the current document (using parseURI(window.location)).

These problems also occur with the more widely supported DOMParser and XMLHttpRequest methods by the way. I have testcases, if anyone is interested.

Grauw

Comments

DOM3 Load from server? by Nige at 2005-08-03 10:17

Thanks for the DOM3 load and save example. I’m currently using XMLHttpRequest to update UI elements in the browser without a page load. Things like select lists, and pop-up selection boxes.

But I’ve also been looking to add conditional (upon availability) code which uses DOM 3 load and save to do this. I also trawled through the spec, and it just does not make it clear AT ALL!

How do you ask your parser to parse some data from a URL instead of a string? And does it HAVE to be valid XML or can it be plain text? The way I work it, is that my servlets generate Javascript which is put into a dynamically created script element, appended to the document and so gets executed and updates the document.

Can the LSParser return plain text? The specs may be “technically correct”, but they are no help unless you’ve already figured out how to use the objects.

Hey Nige, by Grauw at 2005-08-03 22:11

Yeah, some specifications such as the one for HTML and CSS are easy to read, however the DOM ones are a lot more difficult :).

The most important object is the LSParser. It has a parse function that is used in this example, which accepts an LSInput object (which in turn can have text input). But when you want to load from a file it is more straightforward to use – you just need the parseURI function, which has a string with an URI as parameter. E.g.:

var resultdoc = lsp.parseURI("data.xml");

With regard to plain text, it may be possible using the parseWithContext function, but you would have to try that out.

p.s. and 2. with the LSProgressEvent you can detect the progress of an asynchronous load... that’s pretty cool. I don’t think you can do that with XMLHttpRequest...

by Nige at 2005-08-05 13:27

OK, I’ve got an XML document coming through. As you said, I just had to use parseURI().

It looks like it will only accept XML documents. I imagine if they’re not legal XML, you won’t get anything.

I can live with this. I can change my servlets which produce the javascript to put the code into a CDATA. In the browser, I would get that through its ID, and do

new Function(cdataNode.data).call().;

Just one thing. I’d like to be able to identify in the servlet, whether the request is from an XMLHttpRequest, or an LSParser so that I can produce output which will work with either method.

In the XMLHttpRequest, I can set headers, so I could set the “Accept” header to “text/javascript”. This would enable my servlet to decide because Opera sends the Accept header as

text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1

There are a few inadequacies with the design of the DOM3 load/save API. It’s designed from an XML programmer’s viewpoint with not much input from the HTTP/web programmer’s view. No ability to set headers, or set the HTTP method, or any POST content. No ability to read HTTP response status. And no asynchronous requests.

by Nige at 2005-08-05 13:33

OOPS! I just noticed that there is a mode to pass to createLSParser() to specify asynchronous!

parseWithContext can load plain text, I think... by Grauw at 2005-08-05 20:07

As far as I understand, parseWithContext accepts all document fragments that can be a child of an element, so I’d say that would then also include text nodes... I haven’t tried it, but I think it could work.

Looking at the spec, maybe you can try:

url = 'data.xml';

// create a parser object and an input object for the parser with the string
var lsp = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
var lsi = impl.createLSInput();
lsi.stringData = systemId(url);

// parse the string
var elem = document.createElement('div');
var resultdoc = lsp.parseWithContext(lsi,elem,lsp.ACTION_REPLACE_CHILDREN);

And if everything works the way I think it does, the elem variable would contain the text of the loaded file... But it’s probably not be as simple as that, because what would it do with <, > and & characters, etc.

With regard to headers, I indeed don’t think it allows you to set them. You’re right in that it is designed to handle XML... But, XML is cool! :) And maybe they will add extensions to read documents as text in DOM level 4.

what is the difference with innerHTML? by edtijgen at 2008-12-02 08:35

Hi all,

What would the difference be with adding to the DOM with using innerHTML properties of nodes?

DOM 3 load & save seems to do nothing more then innerHTML but only much more complicated?

Regards,

Ed

Re: what is the difference with innerHTML? by Grauw at 2008-12-03 12:20

Well,

First of all, the reason to post this example was because there weren’t much examples of DOM L&S on the web, in hopes it would be of use to those who want to find out how DOM L&S works. At the time of writing, DOM L&S was the only standardised way of loading, parsing and serialising XML.

Nowadays, XMLHttpRequest is also standardised (and is actually more flexible than DOM L&S because it also allows you to retrieve non-XML content and manipulate request headers), but DOM L&S additionally provides XML parsing and serialisation functionality. This is also covered by the DOMParser and XMLSerializer objects that are available in most browsers, but these are not standardised.

In practice, with the current state of the web, you will probably not use DOM L&S. This because it is not very widely supported, and also lacks some functionality that is provided by the alternatives. Instead you will likely use the combination of XMLHttpRequest, DOMParser and XMLSerializer (and their MSXML ActiveX equivalents).

As for innerHTML, that is very different and for many reasons not a sufficient solution:

  • innerHTML invokes the HTML parser, not the XML parser.
  • innerHTML only works on HTML elements, not on arbitrary XML elements.
  • innerHTML is only able to add content to elements, not create new Documents.
  • innerHTML behaviour for XHTML documents is ill-defined and not compatible across different browsers.

Also I think innerHTML is a rather ugly solution which encourages the bad practice of manipulating documents through strings instead of through the DOM.

The script doesn’t work on Opera 21 by Philippe at 2014-06-25 17:33

Hi,

I tested on a few browsers and it didn’t work on any of them, but, in some (like FireFox and Opera 21), the message telling it doesn’t work is not displayed. I wonder if there would not be a mistake on the script tolerated by some browsers and not by others (but I don’t know where such a mistake would occurs).

Bye.

Re: The script doesn’t work on Opera 21 by Grauw at 2014-06-26 19:42

Hi Philippe,

The script probably stopped working when Opera stopped development on their own rendering engine and replaced it with Webkit. I don’t think other browsers ever implemented DOM3 L&S. I doubt the spec has any future.