getElementsByTagNameNS in DOM

16 views
Skip to first unread message

dbrogdon

unread,
Sep 17, 2010, 7:43:46 PM9/17/10
to v8cgi
I'm getting the following error when I make a call to
'getElementsByTagNameNS()':

TypeError: Object Document has no method 'getElementsByTagNameNS'

That method is supported in DOM Level 2 so I'm surprised by this
error. The code in question looks like this:

var parser = new DOM.DOMParser();
var xmlDoc = parser.parseFromString(xmlStr);
var js_el = xmlDoc.getElementsByTagNameNS('foo', '*');

Is there a different way I'm supposed to call this method?

Ondřej Žára

unread,
Sep 21, 2010, 3:52:03 AM9/21/10
to v8...@googlegroups.com
As far as I recall, I have not (yet) implemented any NS-related methods in the DOM module. If you require some of them, please submit their names as a new issue and I will create them as soon as I have some spare time.


Sincerely,
Ondrej Zara



2010/9/18 dbrogdon <dbro...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "v8cgi" group.
To post to this group, send email to v8...@googlegroups.com.
To unsubscribe from this group, send email to v8cgi+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/v8cgi?hl=en.


Darrell Brogdon

unread,
Sep 21, 2010, 4:03:19 PM9/21/10
to v8...@googlegroups.com
Thanks Ondrej,

So you have to create the DOM methods as part of v8cgi?  I would expect them to automatically be available from libxml?

-D

Darrell Brogdon |
 bloomworlds
  Twitter: @bloomworlds

Darrell Brogdon

unread,
Sep 21, 2010, 5:16:24 PM9/21/10
to v8...@googlegroups.com
I just found dom.js and realized thats where all the DOM methods are defined.  I'm going to try to add getElementsByTagNameNS() in there.

Though I'm still curious as to why those methods have to be written in JS?  Is there not a lower-level library that provides those methods what would allow them to execute faster?  In researching libxml I found that it doesn't necessarily provide full DOM support.

Thanks!
-D


On Sep 21, 2010, at 1:52 AM, Ondřej Žára wrote:

Ondřej Žára

unread,
Sep 22, 2010, 3:54:07 AM9/22/10
to v8...@googlegroups.com
It was actually faster to write the DOM module in plain JavaScript, because its great flexibility allowed me to create all necessary parts rather quickly. There is available also the xerces-based native DOM module, but it is complicated and requires additional stuff (the xerces library, for instance).

Creating DOM module based on libxml is possible as well. It just requires wrapping all relevant libxml methods, adding libxml as dependency and creating a binary ( = platform dependent) dom.{so,dll} module.


Sincerely,
Ondrej Zara



2010/9/21 Darrell Brogdon <dar...@brogdon.net>

Darrell Brogdon

unread,
Sep 22, 2010, 12:36:23 PM9/22/10
to v8...@googlegroups.com
I see what you mean.  It was much easier to implement getElementsByTagNameNS() in JavaScript.  Here's a diff of the changes that I put together last night for you to review.

--- dom.js  2010-09-22 00:24:26.000000000 +0400
+++ /usr/lib/v8cgi/dom.js   2010-09-22 20:46:28.000000000 +0400
@@ -297,6 +297,31 @@
    this.attributes.splice(index, 1); 
 }
 
+Element.prototype.getElementsByTagNameNS = function(namespace, tagname) {
+   var result = [], i=0, len=this.childNodes.length;
+
+   for (;i<len;i++) {
+       var child = this.childNodes[i];
+       if (child.nodeType != Node.ELEMENT_NODE) {
+           continue;
+       }
+
+       if ('*' === namespace && '*' === tagname
+       || '*' === tagname && child.nodeName.match(namespace)
+       || '*' === namespace && child.nodeName.match(tagname)
+       || child.nodeName === namespace + ':' + tagname) {
+           result.push(child);
+       }
+       
+       var sub = child.getElementsByTagNameNS(namespace, tagname);
+
+       for (var j=0;j<sub.length;j++) {
+           result.push(sub[j]);
+       }
+   }
+   return result;
+}
+
 Element.prototype.getElementsByTagName = function(name) {
    var result = []; 
    for (var i=0;i<this.childNodes.length;i++) {
@@ -509,6 +534,7 @@
 }
 
 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
+Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
 
 Document.prototype.cloneNode = function(deep) {
    var elm = new Document();

Ondřej Žára

unread,
Sep 22, 2010, 3:03:01 PM9/22/10
to v8...@googlegroups.com
Hi Darrell,

thanks a lot for fast response and a nice diff! The overall approach seems to be very fine, although I have two comments:

1) the large condition might need additional brackets (separating individual AND-combinations), in order to make it more readable for both users and parsers;

2) the large condition needs to be rewritten a little.

I highly recommend reading https://developer.mozilla.org/en/DOM/element.getElementsByTagNameNS as a starting point. Input arguments are actually "namespaceURI" (i.e. not a prefix) and "localName" (i.e. not a prefixed element name). So, the condition needs to work in a fashion similar to:

if (
  (namespaceURI == "*" && localName == "*")
|| (namespaceURI == "*" && localName == child.localName)
|| (namespaceURI == child.namespaceURI && localName == "*")
)

Your last variant with a colon should be removed, as prefixes are of no use in this method. I also believe that this complex condition might be estetically rewritten into several smaller conditions (one set for namespaceURI, second set for localName) in order to make it more readable.

Finally, we need to decide whether the match should be realized in a case-sensitive fashion or not. Again, the MDC article explains this... and I have no strong opinion on case sensitiveness.

By the way - do you want to become member of v8cgi project? This would allow you to directly commit your changes (after consulting them with me, of course) - and I see them as useful additions; we might also take advantage of getAttributeNS and similar...


Sincerely,
Ondrej Zara






2010/9/22 Darrell Brogdon <dar...@brogdon.net>
Reply all
Reply to author
Forward
0 new messages