Forum Moderators: open

Message Too Old, No Replies

using getElementById() on an XMLDocument object

getElementsByTagName works. getElementById doesn't. why?

         

httpwebwitch

2:59 pm on Jan 11, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I've created an XMLDocument as an object. The XML has some of these in it:

<parameters>
<parameter name="ia" id="ia"></parameter>
<parameter name="ib" id="ib"></parameter>
<parameter name="ic" id="ic"></parameter>
</parameters>

this code works, and returns an array of objects:


var params = xp.getElementsByTagName('parameter');

where "xp" is the XMLDocument object.

however this does nothing:


var params = xp.getElementById('ia');

Does anyone know how to do this?
I even made a DTD for my XML that defines the "id" attribute as an ID
<!ATTLIST parameter id ID #REQUIRED>

gergoe

4:57 pm on Jan 11, 2008 (gmt 0)

10+ Year Member



Quickly looking this up in google reveals the answer to your question, see [subbu.org...]

What it basically says that DTD or XML Schema declarations may not have any effect on xmlrequest, because it is not implemented (in most cases), it is not recommended to rely on this. This page also mentions that doctype declarations are quite often supported, so by forcing your xml stream into a xhtml structure (by defining an xhtml doctype) would make it work, but this is like making a sphere out of a cone...

The preferred way is either to make your own getElementById function, or use the other DOM properties and methods for accessing the nodes, like domNode.childNodes for traversing child nodes, the domDocument.getElementsByTagName() to get a list of elements or the domObj.getAttribute() to retrieve the value of an attribute.

httpwebwitch

5:08 pm on Jan 11, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



making a sphere out of a cone

great imagery btw

This is quite disappointing... Embarking on this project I thought that XMLDocument would have all the same methods as Document. getElementById() is essential to what I'm trying to build. If I build my own then I'll be dealing with a pile of potential compatibility problems.

Perhaps I should try this with XPATH instead, though I hear JS support for XPATH is dodgy

gergoe

3:28 am on Jan 13, 2008 (gmt 0)

10+ Year Member



XPath is something I'd not use in the browsers neither (as you mentioned it as well), this is something for the next decade (how that would be supported, if simple things as printing for example does not work well) :-) I think I'm a bit desperate about the browsers and the way they are developed, but anyway;

Making you own getElementById function is quite simple in a fact, and you can even combine it with the built in one (using the DTD attribute definition) - if one day a browser gives support for that, it will be used instead of the one you made. making your getElementById is not more than a recursive function, which goes through the childNodes, looks for an id attribute, if the right one is found, it returns, otherwise continues enumerating the nodes. You can use functions like hasChildNodes(), hasAttribute() to make it work faster, and perhaps using the nodeType==1 condition is also a good idea (to make sure you do not check the id of a text node). Maybe if you search for "custom getElementById" or something similar on the web, you'll find a function which does the same thing.

What I would do:

// 
// The function you could call from your code when looking for an id
function getElementById(domObj, id) {
if (domObj.getElementById) {
var test = domObj.getElementById(id);
if (typeof(test)!== 'undefined') return test;
}
return findID(domObj, id);
}
//
// The recursive function which reproduces the actual
// getElementById functionality
function findID(domObj, id) {
// Check that the current node has the id you need;
// If not, enumerate child nodes of the current DOM node,
// and call findID with each child element. When one of the
// findID calls returns a DOM object, return from the current
// call with that object. When not found, return nothing (or false);
}