CppXml__.hx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * Copyright (c) 2005, The haXe Project Contributors
  3. * All rights reserved.
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * - Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * - Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  23. * DAMAGE.
  24. */
  25. package cpp;
  26. import Xml;
  27. class CppXml__ {
  28. public static var Element(default,null) : XmlType;
  29. public static var PCData(default,null) : XmlType;
  30. public static var CData(default,null) : XmlType;
  31. public static var Comment(default,null) : XmlType;
  32. public static var DocType(default,null) : XmlType;
  33. public static var Prolog(default,null) : XmlType;
  34. public static var Document(default,null) : XmlType;
  35. private var _nodeName : String;
  36. private var _nodeValue : String;
  37. private var _attributes : Dynamic<String>;
  38. private var _children : Array<Dynamic>;
  39. private var _parent : CppXml__;
  40. private function new() {
  41. }
  42. private static var _parse = cpp.Lib.load("std","parse_xml",2);
  43. public static function parse( xmlData : String ) : CppXml__ {
  44. var x = new CppXml__();
  45. x._children = new Array();
  46. var parser = {
  47. cur : x,
  48. xml : function(name,att) {
  49. var x : Dynamic = new CppXml__();
  50. x._parent = untyped this.cur;
  51. x.nodeType = Xml.Element;
  52. x._nodeName = new String(name);
  53. x._attributes = att;
  54. x._children = new Array();
  55. untyped {
  56. var i = 0;
  57. this.cur.addChild(x);
  58. this.cur = x;
  59. }
  60. },
  61. cdata : function(text) {
  62. var x = new CppXml__();
  63. x._parent = untyped this.cur;
  64. x.nodeType = Xml.CData;
  65. x._nodeValue = new String(text);
  66. untyped this.cur.addChild(x);
  67. },
  68. pcdata : function(text) {
  69. var x = new CppXml__();
  70. x._parent = untyped this.cur;
  71. x.nodeType = Xml.PCData;
  72. x._nodeValue = new String(text);
  73. untyped this.cur.addChild(x);
  74. },
  75. comment : function(text:String) {
  76. var x = new CppXml__();
  77. x._parent = untyped this.cur;
  78. if( untyped text.cca(0) == 63 ) {
  79. x.nodeType = Xml.Prolog;
  80. text = "<"+new String(text)+">";
  81. } else {
  82. x.nodeType = Xml.Comment;
  83. text = "<!--"+new String(text)+"-->";
  84. }
  85. x._nodeValue = text;
  86. untyped this.cur.addChild(x);
  87. },
  88. doctype : function(text) {
  89. var x = new CppXml__();
  90. x._parent = untyped this.cur;
  91. x.nodeType = Xml.DocType;
  92. x._nodeValue = "<!DOCTYPE"+new String(text)+">";
  93. untyped this.cur.addChild(x);
  94. },
  95. done : function() {
  96. untyped this.cur = this.cur._parent;
  97. }
  98. };
  99. untyped _parse(xmlData,parser);
  100. x.nodeType = Xml.Document;
  101. return x;
  102. }
  103. public static function createElement( name : String ) : CppXml__ {
  104. var r = new CppXml__();
  105. r.nodeType = Xml.Element;
  106. r._nodeName = name;
  107. r._attributes = null;
  108. r._children = new Array();
  109. return r;
  110. }
  111. public static function createPCData( data : String ) : CppXml__ {
  112. var r = new CppXml__();
  113. r.nodeType = Xml.PCData;
  114. r._nodeValue = data;
  115. return r;
  116. }
  117. public static function createCData( data : String ) : CppXml__ {
  118. var r = new CppXml__();
  119. r.nodeType = Xml.CData;
  120. r._nodeValue = data;
  121. return r;
  122. }
  123. public static function createComment( data : String ) : CppXml__ {
  124. var r = new CppXml__();
  125. r.nodeType = Xml.Comment;
  126. r._nodeValue = data;
  127. return r;
  128. }
  129. public static function createDocType( data : String ) : CppXml__ {
  130. var r = new CppXml__();
  131. r.nodeType = Xml.DocType;
  132. r._nodeValue = data;
  133. return r;
  134. }
  135. public static function createProlog( data : String ) : CppXml__ {
  136. var r = new CppXml__();
  137. r.nodeType = Xml.Prolog;
  138. r._nodeValue = data;
  139. return r;
  140. }
  141. public static function createDocument() : CppXml__ {
  142. var r = new CppXml__();
  143. r.nodeType = Xml.Document;
  144. r._children = new Array();
  145. return r;
  146. }
  147. /**
  148. Returns the type of the Xml Node. This should be used before
  149. accessing other functions since some might raise an exception
  150. if the node type is not correct.
  151. **/
  152. public var nodeType(default,null) : XmlType;
  153. /**
  154. Returns the node name of an Element.
  155. **/
  156. public var nodeName(getNodeName,setNodeName) : String;
  157. /**
  158. Returns the node value. Only works if the Xml node is not an Element or a Document.
  159. **/
  160. public var nodeValue(getNodeValue,setNodeValue) : String;
  161. private function getNodeName() : String {
  162. if( nodeType != Xml.Element )
  163. throw "bad nodeType";
  164. return _nodeName;
  165. }
  166. private function setNodeName( n : String ) : String {
  167. if( nodeType != Xml.Element )
  168. throw "bad nodeType";
  169. return _nodeName = n;
  170. }
  171. private function getNodeValue() : String {
  172. if( nodeType == Xml.Element || nodeType == Xml.Document )
  173. throw "bad nodeType";
  174. return _nodeValue;
  175. }
  176. private function setNodeValue( v : String ) : String {
  177. if( nodeType == Xml.Element || nodeType == Xml.Document )
  178. throw "bad nodeType";
  179. return _nodeValue = v;
  180. }
  181. private function getParent() : 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. return null;
  194. }
  195. public function remove( att : String ) : Void{
  196. if( nodeType != Xml.Element )
  197. throw "bad nodeType";
  198. Reflect.deleteField( _attributes, att );
  199. return null;
  200. }
  201. public function exists( att : String ) : Bool {
  202. if( nodeType != Xml.Element )
  203. throw "bad nodeType";
  204. return Reflect.hasField( _attributes, att );
  205. }
  206. public function attributes() : Iterator<String> {
  207. if( nodeType != Xml.Element )
  208. throw "bad nodeType";
  209. return Reflect.fields( _attributes ).iterator();
  210. }
  211. public function iterator() : Iterator<Xml> {
  212. if( _children == null )
  213. throw "bad nodetype";
  214. return untyped _children.iterator();
  215. }
  216. public function elements(): Iterator<Xml> {
  217. if( _children == null )
  218. throw "bad nodetype";
  219. var children = _children;
  220. return untyped {
  221. cur: 0,
  222. hasNext : function() {
  223. var k:Int = this.cur;
  224. var l = children.length;
  225. while( k < l ) {
  226. if( children[k].nodeType == Xml.Element )
  227. break;
  228. k += 1;
  229. }
  230. this.cur = k;
  231. return k < l;
  232. },
  233. next : function() {
  234. var k = this.cur;
  235. var l = children.length;
  236. while( k < l ) {
  237. var n = children[k];
  238. k += 1;
  239. if( n.nodeType == Xml.Element ) {
  240. this.cur = k;
  241. return n;
  242. }
  243. }
  244. return null;
  245. }
  246. }
  247. }
  248. public function elementsNamed( name : String ) : Iterator<Xml> {
  249. if( _children == null )
  250. throw "bad nodetype";
  251. var children = _children;
  252. return untyped {
  253. cur: 0,
  254. hasNext : function() {
  255. var k = this.cur;
  256. var l = children.length;
  257. while( k < l ) {
  258. var n = children[k];
  259. if( n.nodeType == Xml.Element && n._nodeName == name )
  260. break;
  261. k++;
  262. }
  263. this.cur = k;
  264. return k < l;
  265. },
  266. next : function() {
  267. var k = this.cur;
  268. var l = children.length;
  269. while( k < l ) {
  270. var n = children[k];
  271. k++;
  272. if( n.nodeType == Xml.Element && n._nodeName == name ) {
  273. this.cur = k;
  274. return n;
  275. }
  276. }
  277. return null;
  278. }
  279. }
  280. }
  281. public function firstChild() : Xml {
  282. if( _children == null )
  283. throw "bad nodetype";
  284. return _children[0];
  285. }
  286. public function firstElement() : Xml {
  287. if( _children == null )
  288. throw "bad nodetype";
  289. for( cur in 0..._children.length ) {
  290. var n:CppXml__ = _children[cur];
  291. if( n.nodeType == Xml.Element )
  292. return n;
  293. }
  294. return null;
  295. }
  296. public function addChild( x_ : Xml ) : Void {
  297. var x:CppXml__ = cast x_;
  298. if( _children == null )
  299. throw "bad nodetype";
  300. if( x._parent != null ) x._parent._children.remove(x);
  301. x._parent = this;
  302. _children.push( x );
  303. return null;
  304. }
  305. function removeChild( x_ : Xml ) : Bool {
  306. var x:CppXml__ = cast x_;
  307. if( _children == null )
  308. throw "bad nodetype";
  309. var b = _children.remove( x );
  310. if( b ) x._parent = null;
  311. return b;
  312. }
  313. public function insertChild( x_ : Xml, pos : Int ) : Void {
  314. var x:CppXml__ = cast x_;
  315. if( _children == null )
  316. throw "bad nodetype";
  317. if( x._parent != null ) x._parent._children.remove(x);
  318. x._parent = this;
  319. _children.insert( pos, x );
  320. return null;
  321. }
  322. public function toString() {
  323. if( nodeType == Xml.PCData )
  324. return _nodeValue;
  325. if( nodeType == Xml.CData )
  326. return "<![CDATA["+_nodeValue+"]]>";
  327. if( nodeType == Xml.Comment || nodeType == Xml.DocType || nodeType == Xml.Prolog )
  328. return _nodeValue;
  329. var s = new StringBuf();
  330. if( nodeType == Xml.Element ) {
  331. s.add("<");
  332. s.add(_nodeName);
  333. for( k in Reflect.fields(_attributes) ) {
  334. s.add(" ");
  335. s.add(k);
  336. s.add("=\"");
  337. s.add(Reflect.field(_attributes,k));
  338. s.add("\"");
  339. }
  340. if( _children.length == 0 ) {
  341. s.add("/>");
  342. return s.toString();
  343. }
  344. s.add(">");
  345. }
  346. for( x in iterator() )
  347. s.add(x);
  348. if( nodeType == Xml.Element ) {
  349. s.add("</");
  350. s.add(_nodeName);
  351. s.add(">");
  352. }
  353. return s.toString();
  354. }
  355. static function __init__() : Void {
  356. Element = "element";
  357. PCData = "pcdata";
  358. CData = "cdata";
  359. Comment = "comment";
  360. DocType = "doctype";
  361. Prolog = "prolog";
  362. Document = "document";
  363. }
  364. }