XmlWire.js 7.3 KB

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