Xml.hx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * Copyright (C)2005-2012 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. enum XmlType {
  23. }
  24. @:coreApi class Xml {
  25. public static var Element(default,null) : XmlType;
  26. public static var PCData(default,null) : XmlType;
  27. public static var CData(default,null) : XmlType;
  28. public static var Comment(default,null) : XmlType;
  29. public static var DocType(default,null) : XmlType;
  30. public static var ProcessingInstruction(default,null) : XmlType;
  31. public static var Document(default,null) : XmlType;
  32. public var nodeName(get,set) : String;
  33. public var nodeValue(get,set) : String;
  34. public var parent(get,null) : Xml;
  35. public var nodeType(default,null) : XmlType;
  36. private var _nodeName : String;
  37. private var _nodeValue : String;
  38. private var _attributes : Dynamic<String>;
  39. private var _children : Array<Xml>;
  40. private var _parent : Xml;
  41. private function new() : Void {
  42. }
  43. private static var _parse = neko.Lib.load("std","parse_xml",2);
  44. public static function parse( str : String ) : Xml {
  45. var x = new Xml();
  46. x._children = new Array();
  47. var parser = {
  48. cur : x,
  49. xml : function(name,att) {
  50. var x : Dynamic = new Xml();
  51. x._parent = untyped __this__.cur;
  52. x.nodeType = Xml.Element;
  53. x._nodeName = new String(name);
  54. x._attributes = att;
  55. x._children = new Array();
  56. untyped {
  57. var f = __dollar__objfields(att);
  58. var i = 0;
  59. var l = __dollar__asize(f);
  60. while( i < l ) {
  61. __dollar__objset(att,f[i], new String(__dollar__objget(att,f[i]))) ;
  62. i++;
  63. }
  64. __this__.cur.addChild(x);
  65. __this__.cur = x;
  66. }
  67. },
  68. cdata : function(text) {
  69. var x : Dynamic = new Xml();
  70. x._parent = untyped __this__.cur;
  71. x.nodeType = Xml.CData;
  72. x._nodeValue = new String(text);
  73. untyped __this__.cur.addChild(x);
  74. },
  75. pcdata : function(text) {
  76. var x : Dynamic = new Xml();
  77. x._parent = untyped __this__.cur;
  78. x.nodeType = Xml.PCData;
  79. x._nodeValue = new String(text);
  80. untyped __this__.cur.addChild(x);
  81. },
  82. comment : function(text) {
  83. var x : Dynamic = new Xml();
  84. x._parent = untyped __this__.cur;
  85. if( untyped __dollar__sget(text,0) == 63 ) {
  86. x.nodeType = Xml.ProcessingInstruction;
  87. text = new String(text);
  88. text = text.substr(1,text.length - 2);
  89. } else {
  90. x.nodeType = Xml.Comment;
  91. text = new String(text);
  92. }
  93. x._nodeValue = text;
  94. untyped __this__.cur.addChild(x);
  95. },
  96. doctype : function(text) {
  97. var x : Dynamic = new Xml();
  98. x._parent = untyped __this__.cur;
  99. x.nodeType = Xml.DocType;
  100. x._nodeValue = new String(text).substr(1);
  101. var p : Xml = untyped __this__.cur;
  102. p.addChild(x);
  103. },
  104. done : function() {
  105. untyped __this__.cur = __this__.cur._parent;
  106. }
  107. };
  108. untyped _parse(str.__s,parser);
  109. x.nodeType = Xml.Document;
  110. return x;
  111. }
  112. public static function createElement( name : String ) : Xml {
  113. var r = new Xml();
  114. r.nodeType = Xml.Element;
  115. r._nodeName = name;
  116. r._attributes = untyped __dollar__new(null);
  117. r._children = new Array();
  118. return r;
  119. }
  120. public static function createPCData( data : String ) : Xml {
  121. var r = new Xml();
  122. r.nodeType = Xml.PCData;
  123. r._nodeValue = data;
  124. return r;
  125. }
  126. public static function createCData( data : String ) : Xml {
  127. var r = new Xml();
  128. r.nodeType = Xml.CData;
  129. r._nodeValue = data;
  130. return r;
  131. }
  132. public static function createComment( data : String ) : Xml {
  133. var r = new Xml();
  134. r.nodeType = Xml.Comment;
  135. r._nodeValue = data;
  136. return r;
  137. }
  138. public static function createDocType( data : String ) : Xml {
  139. var r = new Xml();
  140. r.nodeType = Xml.DocType;
  141. r._nodeValue = data;
  142. return r;
  143. }
  144. public static function createProcessingInstruction( data : String ) : Xml {
  145. var r = new Xml();
  146. r.nodeType = Xml.ProcessingInstruction;
  147. r._nodeValue = data;
  148. return r;
  149. }
  150. public static function createDocument() : Xml {
  151. var r = new Xml();
  152. r.nodeType = Xml.Document;
  153. r._children = new Array();
  154. return r;
  155. }
  156. private function get_nodeName() : String {
  157. if( nodeType != Xml.Element )
  158. throw "bad nodeType";
  159. return _nodeName;
  160. }
  161. private function set_nodeName( n : String ) : String {
  162. if( nodeType != Xml.Element )
  163. throw "bad nodeType";
  164. return _nodeName = n;
  165. }
  166. private function get_nodeValue() : String {
  167. if( nodeType == Xml.Element || nodeType == Xml.Document )
  168. throw "bad nodeType";
  169. return _nodeValue;
  170. }
  171. private function set_nodeValue( v : String ) : String {
  172. if( nodeType == Xml.Element || nodeType == Xml.Document )
  173. throw "bad nodeType";
  174. return _nodeValue = v;
  175. }
  176. private function get_parent() : Xml {
  177. return _parent;
  178. }
  179. public function get( att : String ) : String {
  180. if( nodeType != Xml.Element )
  181. throw "bad nodeType";
  182. return Reflect.field( _attributes, att );
  183. }
  184. public function set( att : String, value : String ) : Void {
  185. if( nodeType != Xml.Element )
  186. throw "bad nodeType";
  187. Reflect.setField (_attributes, att, value );
  188. }
  189. public function remove( att : String ) : Void{
  190. if( nodeType != Xml.Element )
  191. throw "bad nodeType";
  192. Reflect.deleteField( _attributes, att );
  193. }
  194. public function exists( att : String ) : Bool {
  195. if( nodeType != Xml.Element )
  196. throw "bad nodeType";
  197. return Reflect.hasField( _attributes, att );
  198. }
  199. public function attributes() : Iterator<String> {
  200. if( nodeType != Xml.Element )
  201. throw "bad nodeType";
  202. return Reflect.fields( _attributes ).iterator();
  203. }
  204. public function iterator() : Iterator<Xml> {
  205. if( _children == null )
  206. throw "bad nodetype";
  207. return untyped {
  208. cur: 0,
  209. x: this._children,
  210. hasNext : function(){
  211. return __this__.cur < __this__.x.length;
  212. },
  213. next : function(){
  214. return __this__.x[__this__.cur++];
  215. }
  216. }
  217. }
  218. public function elements() : Iterator<Xml> {
  219. if( _children == null )
  220. throw "bad nodetype";
  221. return untyped {
  222. cur: 0,
  223. x: this._children,
  224. hasNext : function() {
  225. var k = __this__.cur;
  226. var l = __this__.x.length;
  227. while( k < l ) {
  228. if( __this__.x[k].nodeType == Xml.Element )
  229. break;
  230. k += 1;
  231. }
  232. __this__.cur = k;
  233. return k < l;
  234. },
  235. next : function() {
  236. var k = __this__.cur;
  237. var l = __this__.x.length;
  238. while( k < l ) {
  239. var n = __this__.x[k];
  240. k += 1;
  241. if( n.nodeType == Xml.Element ) {
  242. __this__.cur = k;
  243. return n;
  244. }
  245. }
  246. return null;
  247. }
  248. }
  249. }
  250. public function elementsNamed( name : String ) : Iterator<Xml> {
  251. if( _children == null )
  252. throw "bad nodetype";
  253. return untyped {
  254. cur: 0,
  255. x: this._children,
  256. hasNext : function() {
  257. var k = __this__.cur;
  258. var l = __this__.x.length;
  259. while( k < l ) {
  260. var n = __this__.x[k];
  261. if( n.nodeType == Xml.Element && n._nodeName == name )
  262. break;
  263. k++;
  264. }
  265. __this__.cur = k;
  266. return k < l;
  267. },
  268. next : function() {
  269. var k = __this__.cur;
  270. var l = __this__.x.length;
  271. while( k < l ) {
  272. var n = __this__.x[k];
  273. k++;
  274. if( n.nodeType == Xml.Element && n._nodeName == name ) {
  275. __this__.cur = k;
  276. return n;
  277. }
  278. }
  279. return null;
  280. }
  281. }
  282. }
  283. public function firstChild() : Xml {
  284. if( _children == null )
  285. throw "bad nodetype";
  286. return _children[0];
  287. }
  288. public function firstElement() : Xml {
  289. if( _children == null )
  290. throw "bad nodetype";
  291. for( cur in 0..._children.length ) {
  292. var n = _children[cur];
  293. if( n.nodeType == Xml.Element )
  294. return n;
  295. }
  296. return null;
  297. }
  298. public function addChild( x : Xml ) : Void {
  299. if( _children == null )
  300. throw "bad nodetype";
  301. if( x._parent != null ) x._parent._children.remove(x);
  302. x._parent = this;
  303. _children.push( x );
  304. }
  305. public function removeChild( x : Xml ) : Bool {
  306. if( _children == null )
  307. throw "bad nodetype";
  308. var b = _children.remove( x );
  309. if( b ) x._parent = null;
  310. return b;
  311. }
  312. public function insertChild( x : Xml, pos : Int ) : Void {
  313. if( _children == null )
  314. throw "bad nodetype";
  315. if( x._parent != null ) x._parent._children.remove(x);
  316. x._parent = this;
  317. _children.insert( pos, x );
  318. }
  319. public function toString() : String {
  320. var s = new StringBuf();
  321. toStringRec(s);
  322. return s.toString();
  323. }
  324. function toStringRec(s: StringBuf) : Void {
  325. switch( nodeType ) {
  326. case Xml.Document:
  327. for( x in _children )
  328. x.toStringRec(s);
  329. case Xml.Element:
  330. s.addChar("<".code);
  331. s.add(_nodeName);
  332. for( k in Reflect.fields(_attributes) ) {
  333. s.addChar(" ".code);
  334. s.add(k);
  335. s.addChar("=".code);
  336. s.addChar("\"".code);
  337. s.add(Reflect.field(_attributes,k));
  338. s.addChar("\"".code);
  339. }
  340. if( _children.length == 0 ) {
  341. s.addChar("/".code);
  342. s.addChar(">".code);
  343. return;
  344. }
  345. s.addChar(">".code);
  346. for( x in _children )
  347. x.toStringRec(s);
  348. s.addChar("<".code);
  349. s.addChar("/".code);
  350. s.add(_nodeName);
  351. s.addChar(">".code);
  352. case Xml.PCData:
  353. s.add(StringTools.htmlEscape(_nodeValue));
  354. case Xml.CData:
  355. s.add("<![CDATA[");
  356. s.add(_nodeValue);
  357. s.add("]]>");
  358. case Xml.Comment:
  359. s.add("<!--");
  360. s.add(_nodeValue);
  361. s.add("-->");
  362. case Xml.DocType:
  363. s.add("<!DOCTYPE ");
  364. s.add(_nodeValue);
  365. s.add(">");
  366. case Xml.ProcessingInstruction:
  367. s.add("<?");
  368. s.add(_nodeValue);
  369. s.add("?>");
  370. }
  371. }
  372. static function __init__() : Void untyped {
  373. Xml.Element = "element";
  374. Xml.PCData = "pcdata";
  375. Xml.CData = "cdata";
  376. Xml.Comment = "comment";
  377. Xml.DocType = "doctype";
  378. Xml.ProcessingInstruction = "processingInstruction";
  379. Xml.Document = "document";
  380. }
  381. }