Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

if(!dojo._hasResource["dojox.wire.XmlWire"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.wire.XmlWire"] = true;
dojo.provide("dojox.wire.XmlWire");

dojo.require("dojox.data.dom");
dojo.require("dojox.wire.Wire");

dojo.declare("dojox.wire.XmlWire", dojox.wire.Wire, {
        //      summary:
        //              A Wire for XML nodes or values (element, attribute and text)
        //      description:
        //              This class accesses XML nodes or value with a simplified XPath
        //              specified to 'path' property.
        //              The root object for this class must be an DOM document or element
        //              node.
        //              "@name" accesses to an attribute value of an element and "text()"
        //              accesses to a text value of an element.
        //              The hierarchy of the elements from the root node can be specified
        //              with slash-separated list, such as "a/b/@c", which specifies
        //              the value of an attribute named "c" of an element named "b" as
        //              a child of another element named "a" of a child of the root node.
        
        _wireClass: "dojox.wire.XmlWire",
        
        constructor: function(/*Object*/args){
                //      summary:
                //              Initialize properties
                //      description:
                //              'args' is just mixed in with no further processing.
                //      args:
                //              Arguments to initialize properties
                //              path:
                //                      A simplified XPath to an attribute, a text or elements
        },
        _getValue: function(/*Node*/object){
                //      summary:
                //              Return an attribute value, a text value or an array of elements
                //      description:
                //              This method first uses a root node passed in 'object' argument
                //              and 'path' property to identify an attribute, a text or
                //              elements.
                //              If 'path' starts with a slash (absolute), the first path
                //              segment is ignored assuming it point to the root node.
                //              (That is, "/a/b/@c" and "b/@c" against a root node access
                //              the same attribute value, assuming the root node is an element
                //              with a tag name, "a".)
                //      object:
                //              A root node
                //      returns:
                //              A value found, otherwise 'undefined'
                if(!object || !this.path){
                        return object; //Node
                }

                var node = object;
                var path = this.path;
                if(path.charAt(0) == '/'){ // absolute
                        // skip the first expression (supposed to select the top node)
                        var i = path.indexOf('/', 1);
                        path = path.substring(i + 1);
                }
                var list = path.split('/');
                var last = list.length - 1;
                for(var i = 0; i < last; i++){
                        node = this._getChildNode(node, list[i]);
                        if(!node){
                                return undefined; //undefined
                        }
                }
                var value = this._getNodeValue(node, list[last]);
                return value; //String||Array
        },

        _setValue: function(/*Node*/object, /*String*/value){
                //      summary:
                //              Set an attribute value or a child text value to an element
                //      description:
                //              This method first uses a root node passed in 'object' argument
                //              and 'path' property to identify an attribute, a text or
                //              elements.
                //              If an intermediate element does not exist, it creates
                //              an element of the tag name in the 'path' segment as a child
                //              node of the current node.
                //              Finally, 'value' argument is set to an attribute or a text
                //              (a child node) of the leaf element.
                //      object:
                //              A root node
                //      value:
                //              A value to set
                if(!this.path){
                        return object; //Node
                }

                var node = object;
                var doc = this._getDocument(node);
                var path = this.path;
                if(path.charAt(0) == '/'){ // absolute
                        var i = path.indexOf('/', 1);
                        if(!node){
                                var name = path.substring(1, i);
                                node = doc.createElement(name);
                                object = node; // to be returned as a new object
                        }
                        // skip the first expression (supposed to select the top node)
                        path = path.substring(i + 1);
                }else{
                        if(!node){
                                return undefined; //undefined
                        }
                }

                var list = path.split('/');
                var last = list.length - 1;
                for(var i = 0; i < last; i++){
                        var child = this._getChildNode(node, list[i]);
                        if(!child){
                                child = doc.createElement(list[i]);
                                node.appendChild(child);
                        }
                        node = child;
                }
                this._setNodeValue(node, list[last], value);
                return object; //Node
        },

        _getNodeValue: function(/*Node*/node, /*String*/exp){
                //      summary:
                //              Return an attribute value, a text value or an array of elements
                //      description:
                //              If 'exp' starts with '@', an attribute value of the specified
                //              attribute is returned.
                //              If 'exp' is "text()", a child text value is returned.
                //              Otherwise, an array of child elements, the tag name of which
                //              match 'exp', is returned.
                //      node:
                //              A node
                //      exp:
                //              An expression for attribute, text or elements
                //      returns:
                //              A value found, otherwise 'undefined'
                var value = undefined;
                if(exp.charAt(0) == '@'){
                        var attribute = exp.substring(1);
                        value = node.getAttribute(attribute);
                }else if(exp == "text()"){
                        var text = node.firstChild;
                        if(text){
                                value = text.nodeValue;
                        }
                }else{ // assume elements
                        value = [];
                        for(var i = 0; i < node.childNodes.length; i++){
                                var child = node.childNodes[i];
                                if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == exp){
                                        value.push(child);
                                }
                        }
                }
                return value; //String||Array
        },

        _setNodeValue: function(/*Node*/node, /*String*/exp, /*String*/value){
                //      summary:
                //              Set an attribute value or a child text value to an element
                //      description:
                //              If 'exp' starts with '@', 'value' is set to the specified
                //              attribute.
                //              If 'exp' is "text()", 'value' is set to a child text.
                //      node:
                //              A node
                //      exp:
                //              An expression for attribute or text
                //      value:
                //              A value to set
                if(exp.charAt(0) == '@'){
                        var attribute = exp.substring(1);
                        if(value){
                                node.setAttribute(attribute, value);
                        }else{
                                node.removeAttribute(attribute);
                        }
                }else if(exp == "text()"){
                        while(node.firstChild){
                                node.removeChild(node.firstChild);
                        }
                        if(value){
                                var text = this._getDocument(node).createTextNode(value);
                                node.appendChild(text);
                        }
                }
                // else not supported
        },

        _getChildNode: function(/*Node*/node, /*String*/name){
                //      summary:
                //              Return a child node
                //      description:
                //              A child element of the tag name specified with 'name' is
                //              returned.
                //              If 'name' ends with an array index, it is used to pick up
                //              the corresponding element from multiple child elements.
                //      node:
                //              A parent node
                //      name:
                //              A tag name      
                //      returns:
                //              A child node
                var index = 1;
                var i1 = name.indexOf('[');
                if(i1 >= 0){
                        var i2 = name.indexOf(']');
                        index = name.substring(i1 + 1, i2);
                        name = name.substring(0, i1);
                }
                var count = 1;
                for(var i = 0; i < node.childNodes.length; i++){
                        var child = node.childNodes[i];
                        if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == name){
                                if(count == index){
                                        return child; //Node
                                }
                                count++;
                        }
                }
                return null; //null
        },

        _getDocument: function(/*Node*/node){
                //      summary:
                //              Return a DOM document
                //      description:
                //              If 'node' is specified, a DOM document of the node is returned.
                //              Otherwise, a DOM document is created.
                //      returns:
                //              A DOM document
                if(node){
                        return (node.nodeType == 9 /* DOCUMENT_NODE */ ? node : node.ownerDocument); //Document
                }else{
                        return dojox.data.dom.createDocument(); //Document
                }
        }
});

}