Here is a small library/wrapper for JavaScript XML. Some parts of it belong to other authors like the Opera serialization and the loading of the XML document from a string. I had to do a lot of work on the part related to namespaces, especially on Opera. At this time, the library doesn’t work under Chrome if the XML document makes use of namespaces. So you will not be able to create XPath expression for namespace-d XML documents under Chrome browser. You will notice that the library exposes two layers, first of them is an abstraction of the native DOM and of all its functionality and the second one is the native DOM its self. I have used this library for different XML related tasks; the most important one in my case is the SOAP library and the .NET DataSet serialization to JavaScript data objects. I’m too lazy to explain it in details, but if you have questions feel free to ask them and I’ll give you an answer as fast as possible. You can download the source from HERE

if (typeof (MG) == 'undefined')
    throw ("MG.Core.js is required!");
    
if(typeof(MG.Collections) === 'undefined')
    throw ("MG.Collections.js is required!");    
    
if (typeof (MG.Xml) == 'undefined')
    MG.Xml = {};

MG.Xml.XmlDocument = function(rootTagName, namespaceURL)
        {
            if(document.implementation && document.implementation.createDocument)
            {
                Document.prototype.loadXML = function(strXML)
                {
                    var domParser = new DOMParser();
                    var xmlDoc = domParser.parseFromString(strXML, "text/xml");
                                                    
                    while(this.hasChildNodes())
      this.removeChild(this.lastChild);
                                                        
                    for(var index = 0; index < xmlDoc.childNodes.length; index++)
                    {
      var impNode = this.importNode(xmlDoc.childNodes[index], true);
                        this.appendChild(impNode);
                    }
                                                    
                    var nsResolvers = new MG.Collections.Dictionary();
                    if(xmlDoc.childNodes.length > 0)
                    {
      nsResolvers = fixNS(strXML);
                    }
                                                    
                    function fixNS(xml)
                    {
      var regEx = /<[a-z\dA-Z\d]+:/g;
                        var results = xml.match(regEx);
                        var prefixes = new MG.Collections.ArrayList();
                        var resolvedPrefixes = new MG.Collections.ArrayList();
                        var unresolvedPrefixes = new MG.Collections.ArrayList();
                                                        
                        var count = results !== null ? results.length : 0;
                        for(var index = 0; index < count; index++)
                        {
       var matchValue = results[index];
       var value = matchValue.slice(1, matchValue.length - 1);
                                                            
                            if(prefixes.IndexOf(value) < 0)
        prefixes.Add(value);
                        }
                                                        
                        regEx = /:[a-zA-Z]+=|[a-zA-Z]+=/g;
                        results = xml.match(regEx);
                                                        
                        count = results !== null ? results.length : 0;
                        var prefixesCount = prefixes.Count();
                        for(var index = 0; index < prefixesCount; index++)
                        {
       var resolved = false;
                            var prefix = prefixes.Item(index);
                            for(var j = 0; j < count; j++)
                            {
        var attribute = results[j];
                                var value= null;
                                if(attribute.indexOf(":") === 0)
         value = attribute.slice(1, attribute.length - 1);
                                else
                                    value = attribute.slice(0, attribute.length - 1);
                                                                    
                                if(prefix === value)
        {
         if(resolvedPrefixes.IndexOf(value) < 0)
          resolvedPrefixes.Add(prefixes.Item(index));
                                                                    
         resolved = true;
                                }
                                else
                                {
                                    if(resolvedPrefixes.IndexOf(value) < 0)
          resolvedPrefixes.Add(value);
                                }
                            }
                                                             
                            if(!resolved)
                            unresolvedPrefixes.Add(prefixes.Item(index));
                        }
                                                         
                        var uniqueNamespaces = new MG.Collections.Dictionary();
                                                         
                        var exPrefixesCount = resolvedPrefixes.Count();
                        for(var index = 0; index < exPrefixesCount; index++)
                        {
       var prefix = resolvedPrefixes.Item(index);
                            var regexS = "\\b" + prefix + "=\s*\".*?\"";
                            var regex = new RegExp(regexS);
                            var results = regex.exec(xml);
                                                            
                            if(results !== null && results.length > 0)
                            {
        var prefixValues = new MG.Collections.ArrayList();
                                for(var j = 0; j < results.length; j++)
                                {
         var value = results[j].substring(prefix.length + 2, results[j].length - 1);
                                    prefixValues.Add(value);
                                }
                                                                
        uniqueNamespaces.Add(prefix, prefixValues);
                            }
                        }
                                                         
       return uniqueNamespaces;
                    }
                                                    
                    function createNSResolvers(node)
                    {
      var childNodes = node.childNodes;
                        for(var index = 0; index < childNodes.length; index++)
                        {
                            var prefix = childNodes[index].prefix;
                            var nsURI = childNodes[index].namespaceURI;
                                                            
                            if(prefix && nsURI)
                            {
        if(!nsResolvers.Item(prefix))
         nsResolvers.Add(prefix, nsURI);
                            }
                                                            
                            createNSResolvers(childNodes[index]);    
                        }
                    }
                                                    
      this.nsResolvers = nsResolvers;
                }
                
                function __getXml()
                {
                    var xmlSerializer = new XMLSerializer();
                    var xml = xmlSerializer.serializeToString(this);
                    return xml;
                }
                
                if(Node.prototype.__defineGetter__)                                
                    Node.prototype.__defineGetter__("xml", __getXml);
                
                return new MG.Xml.XmlNode(document.implementation.createDocument(namespaceURL, rootTagName, null)); 
            }
            else
            {
                var doc = new ActiveXObject("MSXML2.DOMDocument");
                
                if(rootTagName)
                {
                    var prefix = "";
                    var tagName = rootTagName;
                    var pos = rootTagName.indexOf(":");
                    
                    if(pos != -1)
                    {
                        rootTagName = rootTagName.substring(0, pos);
                        tagName = rootTagName.substring(pos + 1);
                    }
                 
                    if (namespaceURL)
                    { 
                        if (!prefix)
                            prefix = "a0";
                    }
                    else
                        prefix = ""; 

                    var text = "<" + (prefix?(prefix+":"):"") + tagName +
                                (namespaceURL?(" xmlns:" + prefix + '="' + namespaceURL +'"'):"") + "/>";
            
                    doc.loadXML(text);
                }
                
                return new MG.Xml.XmlNode(doc); 
            }

        };
        

MG.Xml.XmlNode = function(nativeNode)
    {
        if(nativeNode)
        {
            this.NativeNode = nativeNode;
            this.NativeAttributes = nativeNode.attributes;
            this.NativeChildNodes = nativeNode.childNodes;
        }
    };

MG.Xml.XmlNode.prototype.mdcXPath = function(node, xpathExpression, queryType)
    {
        var xpe = new XPathEvaluator();
        var nsResolver = function(prefix)
                { 
                    var nsResolvers = node.nsResolvers;
                    if(!nsResolvers)
                        nsResolvers = node.ownerDocument.nsResolvers;
                    var item = nsResolvers.Item(prefix);
                    
                    if(item)
                    {
                        if (item.Count() > 0) 
                        {
                            return item.Item(0); 
                        }
                    }
                    else
                        return xpe.createNSResolver(node.ownerDocument == null ? node.documentElement : node.ownerDocument.documentElement);
                };
        
        var result = xpe.evaluate(xpathExpression, node, nsResolver, queryType, null);
        return result;
    };

MG.Xml.XmlNode.prototype.fixNameSpaces = function(node, nsResolvers, xml)
    {
        if(nsResolvers)
        {
            if(node.prefix)
            {
                var nsResolver = nsResolvers.Item(node.prefix);
                if(nsResolver)
                {
                    xml += " " + "xmlns:" + node.prefix + "=\"" + nsResolver + "\"";
                    nsResolvers.Remove(node.prefix);
                }
            }
            
            for(var index = 0; index < node.childNodes.length; index++)
                xml = this.fixNameSpaces(node.childNodes[index], nsResolvers, xml);
        }
            
        return xml;
    }
MG.Xml.XmlNode.prototype.operaSerialize = function(nativeNode)
    {
        var xml = null;
        switch(nativeNode.nodeType) 
        {
            case 1:
                {
                    if(this.Name() === nativeNode.nodeName)
                        xml = "<" + nativeNode.localName;
                    else
                        xml = "<" + nativeNode.tagName;
                    
                    var nsResolvers = null;
                    var xmlnsAdded = false;
                    
                    for (var i = 0; i < nativeNode.attributes.length; i++) 
                    {
                        var localName = nativeNode.attributes[i].localName;
                        var name = nativeNode.attributes[i].name;
                        var value = nativeNode.attributes[i].value;
                        
                        if(this.Name() === nativeNode.nodeName)
                        {
                            if(nativeNode.ownerDocument)
                            {
                                nsResolvers = nativeNode.ownerDocument.nsResolvers;
                                if(nsResolvers && nativeNode.ownerDocument.nsResolvers.Contains(localName))
                                    nsResolvers.Remove(localName);
                            }
                            else
                            {
                                nsResolvers = nativeNode.nsResolvers;
                                if(nsResolvers && nsResolvers.Contains(name))
                                    nsResolvers.Remove(name);
                            }
                        }
                        
                        if(name === "xmlns")
                            xmlnsAdded = true;
                        
                        xml += " " + name + "=\"" + value + "\"";
                    }
                    
                    if(this.Name() === nativeNode.nodeName)
                    {
                        if(!nsResolvers)
                        {
                            if(nativeNode.ownerDocument)
                                nsResolvers = nativeNode.ownerDocument.nsResolvers;
                            else
                                nsResolvers = nativeNode.nsResolvers;
                        }
                        
                        if(nsResolvers)
                        {
                            var item = nsResolvers.Item("xmlns");
                            if(item)
                                xml += " " + "xmlns" + "=\"" + item + "\"";
                            else if(!xmlnsAdded)
                                xml += " " + "xmlns" + "=\"" + "http://tempuri.org/" + "\"";
                        
                            xml = this.fixNameSpaces(nativeNode, nsResolvers, xml);     
                        } 
                    }
                                       
                    xml += ">";
            
                    for (var i = 0; i < nativeNode.childNodes.length; i++)
                        xml += this.operaSerialize(nativeNode.childNodes[i]);
                    
                    if(this.Name() === nativeNode.nodeName)
                        xml += "</" + nativeNode.localName + ">";
                    else
                        xml += "</" + nativeNode.tagName + ">";
                }
             break;
            case 3:
                    xml = nativeNode.nodeValue;
             break;
         case 4:
                    xml = "<![CDATA[" + nativeNode.nodeValue + "]]>";
             break;
         case 7:
                 xml = "<?" + nativeNode.nodevalue + "?>";
             break;
         case 8:
                 xml = "<!--" + nativeNode.nodevalue + "-->";
                break;
            case 9:
                {
                    for (var i = 0; i < nativeNode.childNodes.length; i++)
                        xml += this.operaSerialize(nativeNode.childNodes[i]);
                }
                break;   
        }
        return xml;  
    };
MG.Xml.XmlNode.prototype.ChildNodes = function(index)
    {
        if(this.NativeChildNodes)
        {
            if(arguments.length === 0)
                return new MG.Xml.XmlNodes(this.NativeChildNodes);
            else
            {
                var nativeNode = this.NativeChildNodes[index];
                return (new MG.Xml.XmlNode(nativeNode));
            }
        }
        
        return null;
    };
    
MG.Xml.XmlNode.prototype.NextSibling = function()
    {
        if(this.NativeNode)
            return new MG.Xml.XmlNode(this.NativeNode.nextSibling);
        
        return null;
    };
    
MG.Xml.XmlNode.prototype.FirstChild = function()
    {
        if(this.NativeNode)
            return new MG.Xml.XmlNode(this.NativeNode.firstChild);
        
        return null;
    };

MG.Xml.XmlNode.prototype.Name = function()
    {
        if(this.NativeNode)
        {
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.OPERA)
                return this.NativeNode.nodeName;
            else if(browser.IE)
                return this.NativeNode.nodeName;
        }
       
        return null;
    };
    
MG.Xml.XmlNode.prototype.LocalName = function()
    {
        if(this.NativeNode)
        {
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.OPERA)
                return this.NativeNode.localName;
            else if(browser.IE)
                return this.NativeNode.baseName;
        }
        
        return null;
    };
    
MG.Xml.XmlNode.prototype.Text = function()
    {
        if(this.NativeNode)
        {
            var browser = MG.Browser.getInstance();
            
            if(arguments.length === 1)
            {
                if(browser.NS || browser.OPERA)
                    return this.NativeNode.textContent =  arguments[0];
                else if(browser.IE)
                    return this.NativeNode.text = arguments[0];
            }
            else if(arguments.length === 0)
            {
                if(browser.NS || browser.OPERA)
                    return this.NativeNode.textContent;
                else if(browser.IE)
                    return this.NativeNode.text;
            }
            else
                throw("Only one parameter is expected.");
        }
        
        return null;
    };
    
MG.Xml.XmlNode.prototype.Value = function()
    {
        if(this.NativeNode)
        {
            if(arguments.length === 1)
                this.NativeNode.nodeValue = arguments[0];
            else if(arguments.length === 0)
                return this.NativeNode.nodeValue;
            else
                throw("Only one parameter is expected.");
        }
    };    
    
MG.Xml.XmlNode.prototype.Xml = function()
    {
        if(this.NativeNode)
        {
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.IE)
                return this.NativeNode.xml;
            else if(browser.OPERA)
                return this.NativeNode.xml;
        }
        
        return null;
    };

MG.Xml.XmlNode.prototype.SelectSingleNode = function(xpathExpression)
    {
        if(this.NativeNode)
        {
            var nativeNode = null;
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.OPERA)
            {
                var result = this.mdcXPath(this.NativeNode, xpathExpression, XPathResult.FIRST_ORDERED_NODE_TYPE);
                nativeNode = result ? result.singleNodeValue : null;
            }
            else if(browser.IE)
                nativeNode = this.NativeNode.selectSingleNode(xpathExpression);
            
            if(nativeNode)
                return new MG.Xml.XmlNode(nativeNode);  
        }
        
        return null;
    };
    
MG.Xml.XmlNode.prototype.SelectNodes = function(xpathExpression)
    {
        if(this.NativeNode)
        {
            var nativeNodes = null;
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.OPERA)
            {
                var result = this.mdcXPath(this.NativeNode, xpathExpression, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
                
                if(result)
                {
                    var pseudoNodes = new MG.Collections.ArrayList();
                    for(var index = 0; index < result.snapshotLength; index++)
                        pseudoNodes.Add(new MG.Xml.XmlNode(result.snapshotItem(index)));
                        
                   nativeNodes = pseudoNodes;
                }
            }
            else if(browser.IE)
                nativeNodes = this.NativeNode.selectNodes(xpathExpression);
            if(nativeNodes)
                return new MG.Xml.XmlNodes(nativeNodes);
        }
                
        return null;
    };
    
MG.Xml.XmlNode.prototype.CreateNode = function(type, name, namespaceURI)
    {
        if(this.NativeNode)
        {
            var nativeNode = this.NativeNode.createNode(type, name, namespaceURI);
            if(nativeNode)
                return new MG.Xml.XmlNode(nativeNode);
        }
                
        return null;
    };
    
MG.Xml.XmlNode.prototype.AppendChild = function(node)
    {
        if(this.NativeNode)
            this.NativeNode.appendChild(node.NativeNode);
    };
    
MG.Xml.XmlNode.prototype.RemoveChild = function(node)
    {
        if(this.NativeNode)
            this.NativeNode.removeChild(node.NativeNode);
    };
    
MG.Xml.XmlNode.prototype.ReplaceChild = function(newNode, oldNode)
    {
        if(this.NativeNode)
            this.NativeNode.replaceChild(newNode.NativeNode, oldNode.NativeNode);
    };
    
MG.Xml.XmlNode.prototype.ParentNode = function()
    {
        if(this.NativeNode)
            return new MG.Xml.XmlNode(this.NativeNode.parentNode);
                
        return null;
    };
    
MG.Xml.XmlNode.prototype.Prefix = function()
    {
        if(this.NativeNode)
            return this.NativeNode.prefix;
                
        return null;
    };
    
MG.Xml.XmlNode.prototype.LoadXML = function(xmlString)
    {
        this.NativeNode.loadXML(xmlString);
    };

MG.Xml.XmlNode.prototype.SetAttributeNode = function(attributeNode)
    {
        if(this.NativeNode)
            this.NativeNode.setAttributeNode(attributeNode.NativeAttribute);
    };
    
MG.Xml.XmlNode.prototype.SetAttribute = function(name, value)
    {
        if(this.NativeNode)
            this.NativeNode.setAttribute(name, value);
    };    
    
MG.Xml.XmlNode.prototype.Attributes = function()
    {
        if(this.NativeAttributes)
            return new MG.Xml.Attributes(this.NativeAttributes);
            
        return null;
    };
    
MG.Xml.Attributes = function(nativeAttributes)
    {
        this.NativeAttributes = nativeAttributes;
    };

MG.Xml.Attributes.prototype.GetNamedItem = function(itemName)
    {
        if(this.NativeAttributes)
           return new MG.Xml.Attribute(this.NativeAttributes.getNamedItem(itemName));
           
       return null;
    };
    
MG.Xml.Attributes.prototype.Item = function(index)
    {
        if(this.NativeAttributes)
            return new MG.Xml.Attribute(this.NativeAttributes[index]);
            
        return null;
    };
    
MG.Xml.Attributes.prototype.Length = function()
    {
        if(this.NativeAttributes)
            return this.NativeAttributes.length;
            
        return null;
    };
    
MG.Xml.Attribute = function(nativeAttribute)
    {
        this.NativeAttribute = nativeAttribute;
    };
    
MG.Xml.Attribute.prototype.Value = function()
    {
        if(this.NativeAttribute)
            return this.NativeAttribute.value;
    };

MG.Xml.Attribute.prototype.Name = function()
    {
        if(this.NativeAttribute)
            return this.NativeAttribute.name;
    };

MG.Xml.XmlNodes = function(nativeNodes)
    {
        var isPseudo = false;
        var browser = MG.Browser.getInstance();
        if(browser.NS || browser.OPERA)
        {
            if(nativeNodes.constructor === MG.Collections.ArrayList.constructor)
                isPseudo = true;
        }
        else if(browser.IE)
        {
            if(nativeNodes.constructor === MG.Collections.ArrayList)
                isPseudo = true;
        }
        
        if(!isPseudo)
        {
            this.NativeNodes = new MG.Collections.ArrayList();
            for(var index = 0; index < nativeNodes.length; index++)
                this.NativeNodes.Add(new MG.Xml.XmlNode(nativeNodes[index]));
        }
        else
            this.NativeNodes = nativeNodes;
    };
   
MG.Xml.XmlNodes.prototype.Length = function()
    {
        if(this.NativeNodes)
        {
            var browser = MG.Browser.getInstance();
            if(browser.NS || browser.OPERA)
            {
                if(this.NativeNodes.constructor === MG.Collections.ArrayList.constructor)
                    return this.NativeNodes.Count();
                else
                    return this.NativeNodes.length;
            }
            else if(browser.IE)
            {
                if(this.NativeNodes.constructor === MG.Collections.ArrayList)
                    return this.NativeNodes.Count();
                else    
                    return this.NativeNodes.length;
            }
        }
            
        return null;
    };
    
MG.Xml.XmlNodes.prototype.Item = function(index)
    {
        if(this.NativeNodes)
            return this.NativeNodes.Item(index);    
        
        return null;
    };