NativeXml.hx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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. package neko;
  23. enum XmlType {
  24. }
  25. typedef NativeXml = Xml;
  26. class Xml {
  27. public static var Element(default,null) : XmlType;
  28. public static var PCData(default,null) : XmlType;
  29. public static var CData(default,null) : XmlType;
  30. public static var Comment(default,null) : XmlType;
  31. public static var DocType(default,null) : XmlType;
  32. public static var ProcessingInstruction(default,null) : XmlType;
  33. public static var Document(default,null) : XmlType;
  34. public var nodeName(get,set) : String;
  35. public var nodeValue(get,set) : String;
  36. public var parent(get,null) : Xml;
  37. public var nodeType(default,null) : XmlType;
  38. private var _nodeName : String;
  39. private var _nodeValue : String;
  40. private var _attributes : Dynamic<String>;
  41. private var _children : Array<Xml>;
  42. private var _parent : Xml;
  43. private function new() : Void {
  44. }
  45. private static var _parse = neko.Lib.load("std","parse_xml",2);
  46. public static function parse( str : String ) : Xml {
  47. var x = new Xml();
  48. x._children = new Array();
  49. var parser = {
  50. cur : x,
  51. add : function(x:Dynamic) {
  52. untyped __this__.cur._children.push(x);
  53. },
  54. xml : function(name,att) {
  55. var x : Dynamic = new Xml();
  56. x._parent = untyped __this__.cur;
  57. x.nodeType = Xml.Element;
  58. x._nodeName = new String(name);
  59. x._attributes = att;
  60. x._children = new Array();
  61. untyped {
  62. var f = __dollar__objfields(att);
  63. var i = 0;
  64. var l = __dollar__asize(f);
  65. while( i < l ) {
  66. __dollar__objset(att,f[i], new String(__dollar__objget(att,f[i]))) ;
  67. i++;
  68. }
  69. __this__.add(x);
  70. __this__.cur = x;
  71. }
  72. },
  73. cdata : function(text) {
  74. var x : Dynamic = new Xml();
  75. x._parent = untyped __this__.cur;
  76. x.nodeType = Xml.CData;
  77. x._nodeValue = new String(text);
  78. untyped __this__.add(x);
  79. },
  80. pcdata : function(text) {
  81. var x : Dynamic = new Xml();
  82. x._parent = untyped __this__.cur;
  83. x.nodeType = Xml.PCData;
  84. x._nodeValue = new String(text);
  85. untyped __this__.add(x);
  86. },
  87. comment : function(text) {
  88. var x : Dynamic = new Xml();
  89. x._parent = untyped __this__.cur;
  90. if( untyped __dollar__sget(text,0) == 63 ) {
  91. x.nodeType = Xml.ProcessingInstruction;
  92. text = new String(text);
  93. text = text.substr(1,text.length - 2);
  94. } else {
  95. x.nodeType = Xml.Comment;
  96. text = new String(text);
  97. }
  98. x._nodeValue = text;
  99. untyped __this__.add(x);
  100. },
  101. doctype : function(text) {
  102. var x : Dynamic = new Xml();
  103. x._parent = untyped __this__.cur;
  104. x.nodeType = Xml.DocType;
  105. x._nodeValue = new String(text).substr(1);
  106. var p : Xml = untyped __this__.cur;
  107. p.addChild(x);
  108. },
  109. done : function() {
  110. untyped __this__.cur = __this__.cur._parent;
  111. }
  112. };
  113. untyped _parse(str.__s,parser);
  114. x.nodeType = Xml.Document;
  115. return x;
  116. }
  117. public static function createElement( name : String ) : Xml {
  118. var r = new Xml();
  119. r.nodeType = Xml.Element;
  120. r._nodeName = name;
  121. r._attributes = untyped __dollar__new(null);
  122. r._children = new Array();
  123. return r;
  124. }
  125. public static function createPCData( data : String ) : Xml {
  126. var r = new Xml();
  127. r.nodeType = Xml.PCData;
  128. r._nodeValue = data;
  129. return r;
  130. }
  131. public static function createCData( data : String ) : Xml {
  132. var r = new Xml();
  133. r.nodeType = Xml.CData;
  134. r._nodeValue = data;
  135. return r;
  136. }
  137. public static function createComment( data : String ) : Xml {
  138. var r = new Xml();
  139. r.nodeType = Xml.Comment;
  140. r._nodeValue = data;
  141. return r;
  142. }
  143. public static function createDocType( data : String ) : Xml {
  144. var r = new Xml();
  145. r.nodeType = Xml.DocType;
  146. r._nodeValue = data;
  147. return r;
  148. }
  149. public static function createProcessingInstruction( data : String ) : Xml {
  150. var r = new Xml();
  151. r.nodeType = Xml.ProcessingInstruction;
  152. r._nodeValue = data;
  153. return r;
  154. }
  155. public static function createDocument() : Xml {
  156. var r = new Xml();
  157. r.nodeType = Xml.Document;
  158. r._children = new Array();
  159. return r;
  160. }
  161. private function get_nodeName() : String {
  162. if( nodeType != Xml.Element )
  163. throw "bad nodeType";
  164. return _nodeName;
  165. }
  166. private function set_nodeName( n : String ) : String {
  167. if( nodeType != Xml.Element )
  168. throw "bad nodeType";
  169. return _nodeName = n;
  170. }
  171. private function get_nodeValue() : String {
  172. if( nodeType == Xml.Element || nodeType == Xml.Document )
  173. throw "bad nodeType";
  174. return _nodeValue;
  175. }
  176. private function set_nodeValue( v : String ) : String {
  177. if( nodeType == Xml.Element || nodeType == Xml.Document )
  178. throw "bad nodeType";
  179. return _nodeValue = v;
  180. }
  181. private function get_parent() : Xml {
  182. return _parent;
  183. }
  184. public function get( att : String ) : String {
  185. if( nodeType != Xml.Element )
  186. throw "bad nodeType";
  187. return Reflect.field( _attributes, att );
  188. }
  189. public function set( att : String, value : String ) : Void {
  190. if( nodeType != Xml.Element )
  191. throw "bad nodeType";
  192. Reflect.setField (_attributes, att, value );
  193. }
  194. public function remove( att : String ) : Void{
  195. if( nodeType != Xml.Element )
  196. throw "bad nodeType";
  197. Reflect.deleteField( _attributes, att );
  198. }
  199. public function exists( att : String ) : Bool {
  200. if( nodeType != Xml.Element )
  201. throw "bad nodeType";
  202. return Reflect.hasField( _attributes, att );
  203. }
  204. public function attributes() : Iterator<String> {
  205. if( nodeType != Xml.Element )
  206. throw "bad nodeType";
  207. return Reflect.fields( _attributes ).iterator();
  208. }
  209. public function iterator() : Iterator<Xml> {
  210. if( _children == null )
  211. throw "bad nodetype";
  212. return untyped {
  213. cur: 0,
  214. x: this._children,
  215. hasNext : function(){
  216. return __this__.cur < __this__.x.length;
  217. },
  218. next : function(){
  219. return __this__.x[__this__.cur++];
  220. }
  221. }
  222. }
  223. public function elements() : Iterator<Xml> {
  224. if( _children == null )
  225. throw "bad nodetype";
  226. return untyped {
  227. cur: 0,
  228. x: this._children,
  229. hasNext : function() {
  230. var k = __this__.cur;
  231. var l = __this__.x.length;
  232. while( k < l ) {
  233. if( __this__.x[k].nodeType == Xml.Element )
  234. break;
  235. k += 1;
  236. }
  237. __this__.cur = k;
  238. return k < l;
  239. },
  240. next : function() {
  241. var k = __this__.cur;
  242. var l = __this__.x.length;
  243. while( k < l ) {
  244. var n = __this__.x[k];
  245. k += 1;
  246. if( n.nodeType == Xml.Element ) {
  247. __this__.cur = k;
  248. return n;
  249. }
  250. }
  251. return null;
  252. }
  253. }
  254. }
  255. public function elementsNamed( name : String ) : Iterator<Xml> {
  256. if( _children == null )
  257. throw "bad nodetype";
  258. return untyped {
  259. cur: 0,
  260. x: this._children,
  261. hasNext : function() {
  262. var k = __this__.cur;
  263. var l = __this__.x.length;
  264. while( k < l ) {
  265. var n = __this__.x[k];
  266. if( n.nodeType == Xml.Element && n._nodeName == name )
  267. break;
  268. k++;
  269. }
  270. __this__.cur = k;
  271. return k < l;
  272. },
  273. next : function() {
  274. var k = __this__.cur;
  275. var l = __this__.x.length;
  276. while( k < l ) {
  277. var n = __this__.x[k];
  278. k++;
  279. if( n.nodeType == Xml.Element && n._nodeName == name ) {
  280. __this__.cur = k;
  281. return n;
  282. }
  283. }
  284. return null;
  285. }
  286. }
  287. }
  288. public function firstChild() : Xml {
  289. if( _children == null )
  290. throw "bad nodetype";
  291. return _children[0];
  292. }
  293. public function firstElement() : Xml {
  294. if( _children == null )
  295. throw "bad nodetype";
  296. for( cur in 0..._children.length ) {
  297. var n = _children[cur];
  298. if( n.nodeType == Xml.Element )
  299. return n;
  300. }
  301. return null;
  302. }
  303. public function addChild( x : Xml ) : Void {
  304. if( _children == null )
  305. throw "bad nodetype";
  306. if( x._parent != null ) x._parent._children.remove(x);
  307. x._parent = this;
  308. _children.push( x );
  309. }
  310. public function removeChild( x : Xml ) : Bool {
  311. if( _children == null )
  312. throw "bad nodetype";
  313. var b = _children.remove( x );
  314. if( b ) x._parent = null;
  315. return b;
  316. }
  317. public function insertChild( x : Xml, pos : Int ) : Void {
  318. if( _children == null )
  319. throw "bad nodetype";
  320. if( x._parent != null ) x._parent._children.remove(x);
  321. x._parent = this;
  322. _children.insert( pos, x );
  323. }
  324. public function toString() : String {
  325. var s = new StringBuf();
  326. toStringRec(s);
  327. return s.toString();
  328. }
  329. function toStringRec(s: StringBuf) : Void {
  330. switch( nodeType ) {
  331. case Xml.Document:
  332. for( x in _children )
  333. x.toStringRec(s);
  334. case Xml.Element:
  335. s.addChar("<".code);
  336. s.add(_nodeName);
  337. for( k in Reflect.fields(_attributes) ) {
  338. s.addChar(" ".code);
  339. s.add(k);
  340. s.addChar("=".code);
  341. s.addChar("\"".code);
  342. s.add(Reflect.field(_attributes,k));
  343. s.addChar("\"".code);
  344. }
  345. if( _children.length == 0 ) {
  346. s.addChar("/".code);
  347. s.addChar(">".code);
  348. return;
  349. }
  350. s.addChar(">".code);
  351. for( x in _children )
  352. x.toStringRec(s);
  353. s.addChar("<".code);
  354. s.addChar("/".code);
  355. s.add(_nodeName);
  356. s.addChar(">".code);
  357. case Xml.PCData:
  358. s.add(StringTools.htmlEscape(_nodeValue));
  359. case Xml.CData:
  360. s.add("<![CDATA[");
  361. s.add(_nodeValue);
  362. s.add("]]>");
  363. case Xml.Comment:
  364. s.add("<!--");
  365. s.add(_nodeValue);
  366. s.add("-->");
  367. case Xml.DocType:
  368. s.add("<!DOCTYPE ");
  369. s.add(_nodeValue);
  370. s.add(">");
  371. case Xml.ProcessingInstruction:
  372. s.add("<?");
  373. s.add(_nodeValue);
  374. s.add("?>");
  375. }
  376. }
  377. static function __init__() : Void untyped {
  378. Xml.Element = "element";
  379. Xml.PCData = "pcdata";
  380. Xml.CData = "cdata";
  381. Xml.Comment = "comment";
  382. Xml.DocType = "doctype";
  383. Xml.ProcessingInstruction = "processingInstruction";
  384. Xml.Document = "document";
  385. }
  386. }