Javascript: getElementById() for XML fragments and arbitrary XML documents + getElementsByAttribute()

Why I never wrote this function before is a mystery.

In my experience, people* designing XML response docs for Ajax-y type applications often re-use xHMTL attributes. href and src are common examples. One other one that I’ve run into pretty often is id. Since Javascript’s getElementById() relies on the document’s DTD defining the id attribute doing something like

xml_document.getElementById('myid')

returns null when pointed at the sort of informal XML documents people often spit out for these kind of things.

To remedy that, I wrote this:

function getElementByIdMXL(the_node,the_id) {
	//get all the tags in the doc
	node_tags = the_node.getElementsByTagName('*');
	for (i=0;i<node_tags.length;i++) {
	//is there an id attribute?
		if (node_tags[i].hasAttribute('id')) {
			//if there is, test its value
			if (node_tags[i].getAttribute('id') == the_id) {
				//and return it if it matches
				return node_tags[i];
			}
		}
	}
}

where the_node is the DTD-less XML document and the_id is the id to search for. It’s a pretty simple script really, but it would have been useful a couple of times in recent memory.

Looking at that bit of code made me want to create a version that searched for arbitrary attribute/value pairs. Since I’ve looked at getElementsByClass a thousand times it practically wrote itself:

function getElementsByAttribute(the_attribute, the_value, the_node) {
        if ( the_node == null )
             the_node = document;
        var node_tags = the_node.getElementsByTagName('*');
	var results = new Array();
	for (i=0, j=0; i<node_tags.length;i++) {
		if (node_tags[i].hasAttribute(the_attribute)) {
			if (node_tags[i].getAttribute(the_attribute) == the_value) {
			  	results[j] = node_tags[i];
            	                j++;
			}
		}
	}
	return results;
}

The only real difference between the two is the second returns an array and the first just returns the one object.

These aren’t really groundbreaking, of course. They’re just a couple of bits of code I thought I’d share…

*that definitely includes me

7 thoughts on “Javascript: getElementById() for XML fragments and arbitrary XML documents + getElementsByAttribute()

  1. A few notes…

    1.) I hope this wasn’t meant as a replacement for the getElementsByClass, as it will fail if more than one class is applied to an element. 😉

    2.) Minor, but you can save some code, and avoid some global variables (i & j), with a few adjustments to your function.

    function getElementsByAttribute(the_node, the_attribute, the_value){
    var node_tags = the_node.getElementsByTagName(‘*’);
    var results = [];
    for(var i=0;i

  2. Doh!… Less than symbol stripped out… lets try this:

    function getElementsByAttribute(the_node, the_attribute, the_value){
    var node_tags = the_node.getElementsByTagName(‘*’);
    var results = [];
    for(var i=0;i<node_tags.length;i++){
    if(node_tags[i].hasAttribute(the_attribute)){
    if(node_tags[i].getAttribute(the_attribute) == the_value){
    results.push(node_tags[i]);
    }
    }
    }
    return results;
    }

  3. definitely not meant as a replacement for getElementsByClass. To be honest, I’m not sure how I would use it as it was a pure “hey, I could do that too” kind of thing. I can imagine some uses and once I put it to use, I imagine there’ll be some adjustments to make.

    Speaking of which-

    push(). *duh* Thanks 🙂

  4. It’s very help full, but it’s a problem in IE.
    in IE, its doesn’t work ! IE Sayd, “Error: Object Doesn’t Support This Property or Method”.

  5. i will try this out, but I’m thinking 2 questions. 1) Does it make an “index” of the id’s? because this is one of the appealing performance-boosting aspects of the getElementById() method. and
    2) Is it possible to have a DTD that just defines a few things, rather then explicitly defining all the tags and everything? If so, can you show the specific requirements of just defining the id thing?

Leave a Reply

Your email address will not be published. Required fields are marked *