source: Dev/branches/rest-dojo-ui/client/dojox/wire/XmlWire.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 6.9 KB
Line 
1dojo.provide("dojox.wire.XmlWire");
2
3dojo.require("dojox.xml.parser");
4dojo.require("dojox.wire.Wire");
5
6dojo.declare("dojox.wire.XmlWire", dojox.wire.Wire, {
7        //      summary:
8        //              A Wire for XML nodes or values (element, attribute and text)
9        //      description:
10        //              This class accesses XML nodes or value with a simplified XPath
11        //              specified to 'path' property.
12        //              The root object for this class must be an DOM document or element
13        //              node.
14        //              "@name" accesses to an attribute value of an element and "text()"
15        //              accesses to a text value of an element.
16        //              The hierarchy of the elements from the root node can be specified
17        //              with slash-separated list, such as "a/b/@c", which specifies
18        //              the value of an attribute named "c" of an element named "b" as
19        //              a child of another element named "a" of a child of the root node.
20       
21        _wireClass: "dojox.wire.XmlWire",
22       
23        constructor: function(/*Object*/args){
24                //      summary:
25                //              Initialize properties
26                //      description:
27                //              'args' is just mixed in with no further processing.
28                //      args:
29                //              Arguments to initialize properties
30                //              path:
31                //                      A simplified XPath to an attribute, a text or elements
32        },
33        _getValue: function(/*Node*/object){
34                //      summary:
35                //              Return an attribute value, a text value or an array of elements
36                //      description:
37                //              This method first uses a root node passed in 'object' argument
38                //              and 'path' property to identify an attribute, a text or
39                //              elements.
40                //              If 'path' starts with a slash (absolute), the first path
41                //              segment is ignored assuming it point to the root node.
42                //              (That is, "/a/b/@c" and "b/@c" against a root node access
43                //              the same attribute value, assuming the root node is an element
44                //              with a tag name, "a".)
45                //      object:
46                //              A root node
47                //      returns:
48                //              A value found, otherwise 'undefined'
49                if(!object || !this.path){
50                        return object; //Node
51                }
52
53                var node = object;
54                var path = this.path;
55                var i;
56                if(path.charAt(0) == '/'){ // absolute
57                        // skip the first expression (supposed to select the top node)
58                        i = path.indexOf('/', 1);
59                        path = path.substring(i + 1);
60                }
61                var list = path.split('/');
62                var last = list.length - 1;
63                for(i = 0; i < last; i++){
64                        node = this._getChildNode(node, list[i]);
65                        if(!node){
66                                return undefined; //undefined
67                        }
68                }
69                var value = this._getNodeValue(node, list[last]);
70                return value; //String||Array
71        },
72
73        _setValue: function(/*Node*/object, /*String*/value){
74                //      summary:
75                //              Set an attribute value or a child text value to an element
76                //      description:
77                //              This method first uses a root node passed in 'object' argument
78                //              and 'path' property to identify an attribute, a text or
79                //              elements.
80                //              If an intermediate element does not exist, it creates
81                //              an element of the tag name in the 'path' segment as a child
82                //              node of the current node.
83                //              Finally, 'value' argument is set to an attribute or a text
84                //              (a child node) of the leaf element.
85                //      object:
86                //              A root node
87                //      value:
88                //              A value to set
89                if(!this.path){
90                        return object; //Node
91                }
92
93                var node = object;
94                var doc = this._getDocument(node);
95                var path = this.path;
96                var i;
97                if(path.charAt(0) == '/'){ // absolute
98                        i = path.indexOf('/', 1);
99                        if(!node){
100                                var name = path.substring(1, i);
101                                node = doc.createElement(name);
102                                object = node; // to be returned as a new object
103                        }
104                        // skip the first expression (supposed to select the top node)
105                        path = path.substring(i + 1);
106                }else{
107                        if(!node){
108                                return undefined; //undefined
109                        }
110                }
111
112                var list = path.split('/');
113                var last = list.length - 1;
114                for(i = 0; i < last; i++){
115                        var child = this._getChildNode(node, list[i]);
116                        if(!child){
117                                child = doc.createElement(list[i]);
118                                node.appendChild(child);
119                        }
120                        node = child;
121                }
122                this._setNodeValue(node, list[last], value);
123                return object; //Node
124        },
125
126        _getNodeValue: function(/*Node*/node, /*String*/exp){
127                //      summary:
128                //              Return an attribute value, a text value or an array of elements
129                //      description:
130                //              If 'exp' starts with '@', an attribute value of the specified
131                //              attribute is returned.
132                //              If 'exp' is "text()", a child text value is returned.
133                //              Otherwise, an array of child elements, the tag name of which
134                //              match 'exp', is returned.
135                //      node:
136                //              A node
137                //      exp:
138                //              An expression for attribute, text or elements
139                //      returns:
140                //              A value found, otherwise 'undefined'
141                var value = undefined;
142                if(exp.charAt(0) == '@'){
143                        var attribute = exp.substring(1);
144                        value = node.getAttribute(attribute);
145                }else if(exp == "text()"){
146                        var text = node.firstChild;
147                        if(text){
148                                value = text.nodeValue;
149                        }
150                }else{ // assume elements
151                        value = [];
152                        for(var i = 0; i < node.childNodes.length; i++){
153                                var child = node.childNodes[i];
154                                if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == exp){
155                                        value.push(child);
156                                }
157                        }
158                }
159                return value; //String||Array
160        },
161
162        _setNodeValue: function(/*Node*/node, /*String*/exp, /*String*/value){
163                //      summary:
164                //              Set an attribute value or a child text value to an element
165                //      description:
166                //              If 'exp' starts with '@', 'value' is set to the specified
167                //              attribute.
168                //              If 'exp' is "text()", 'value' is set to a child text.
169                //      node:
170                //              A node
171                //      exp:
172                //              An expression for attribute or text
173                //      value:
174                //              A value to set
175                if(exp.charAt(0) == '@'){
176                        var attribute = exp.substring(1);
177                        if(value){
178                                node.setAttribute(attribute, value);
179                        }else{
180                                node.removeAttribute(attribute);
181                        }
182                }else if(exp == "text()"){
183                        while(node.firstChild){
184                                node.removeChild(node.firstChild);
185                        }
186                        if(value){
187                                var text = this._getDocument(node).createTextNode(value);
188                                node.appendChild(text);
189                        }
190                }
191                // else not supported
192        },
193
194        _getChildNode: function(/*Node*/node, /*String*/name){
195                //      summary:
196                //              Return a child node
197                //      description:
198                //              A child element of the tag name specified with 'name' is
199                //              returned.
200                //              If 'name' ends with an array index, it is used to pick up
201                //              the corresponding element from multiple child elements.
202                //      node:
203                //              A parent node
204                //      name:
205                //              A tag name
206                //      returns:
207                //              A child node
208                var index = 1;
209                var i1 = name.indexOf('[');
210                if(i1 >= 0){
211                        var i2 = name.indexOf(']');
212                        index = name.substring(i1 + 1, i2);
213                        name = name.substring(0, i1);
214                }
215                var count = 1;
216                for(var i = 0; i < node.childNodes.length; i++){
217                        var child = node.childNodes[i];
218                        if(child.nodeType === 1 /* ELEMENT_NODE */ && child.nodeName == name){
219                                if(count == index){
220                                        return child; //Node
221                                }
222                                count++;
223                        }
224                }
225                return null; //null
226        },
227
228        _getDocument: function(/*Node*/node){
229                //      summary:
230                //              Return a DOM document
231                //      description:
232                //              If 'node' is specified, a DOM document of the node is returned.
233                //              Otherwise, a DOM document is created.
234                //      returns:
235                //              A DOM document
236                if(node){
237                        return (node.nodeType == 9 /* DOCUMENT_NODE */ ? node : node.ownerDocument); //Document
238                }else{
239                        return dojox.xml.parser.parse(); //Document
240                }
241        }
242});
Note: See TracBrowser for help on using the repository browser.