XmlWire.js 8.0 KB

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