source: Dev/trunk/src/client/dojox/wire/XmlWire.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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                //
31                //              - path: 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.