Guest User

Untitled

a guest
Jul 22nd, 2018
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.41 KB | None | 0 0
  1. #define xml_init
  2. //xml_init();
  3.  
  4. globalvar
  5. //object globals
  6. xml_node,
  7. xml_doctype,
  8. xml_declaration,
  9. xml_document,
  10. xml_element,
  11. xml_text,
  12. //other globals
  13. xml_debug,
  14. ;
  15.  
  16. //make node objects
  17. xml_node = object_add();
  18. xml_doctype = object_add();
  19. xml_declaration = object_add();
  20. xml_document = object_add();
  21. xml_element = object_add();
  22. xml_text = object_add();
  23.  
  24. //define parental relationships on object level
  25. object_set_parent(xml_doctype , xml_node);
  26. object_set_parent(xml_declaration , xml_node);
  27. object_set_parent(xml_document , xml_node);
  28. object_set_parent(xml_element , xml_node);
  29. object_set_parent(xml_text , xml_node);
  30.  
  31. //other global variables
  32. xml_debug = 1; // debug: 0 = no messages; 1 = errors; 2 = notices
  33.  
  34. return(true);
  35.  
  36. #define xml_clear
  37. //xml_clear([document:id])
  38. var argument_num;if(!variable_local_exists('argument_count')){var a,i;a=0;for(i=0;i<16;i+=1){if(string(argument[i])!="0"){a=i+1;}}argument_num=a;}else{argument_num=argument_count;}
  39.  
  40. // Have all nodes that meet the document requirements (if any) commit suicide
  41.  
  42. var document;
  43. document = false;
  44. if(argument_num>0){
  45. document = argument0;
  46. }
  47.  
  48. with(xml_node){
  49. if(self.document==document || !document){
  50. //ds_map_destroy(attr_map)
  51. instance_destroy();
  52. }
  53. }
  54.  
  55. return(true);
  56.  
  57. #define xml_read
  58. //xml_read(xml:str,[parent:id])
  59. var argument_num;if(!variable_local_exists('argument_count')){var a,i;a=0;for(i=0;i<16;i+=1){if(string(argument[i])!="0"){a=i+1;}}argument_num=a;}else{argument_num=argument_count;}
  60.  
  61. // Read XML as string and convert it to node instances
  62.  
  63. var xml,document,parent,
  64. stack,node,text_node,
  65. buffer,buffer_start,offset,
  66. type,name,
  67. i,c,tag_end,
  68. closing,autoclose,
  69. txt,cdata,comment,comments;
  70.  
  71. xml = argument0;
  72. parent = noone;
  73. if(argument_num>1){
  74. parent = argument[1];
  75. }
  76.  
  77. //convert tabs to spaces
  78. xml=string_replace_all(xml,chr(9)," ");
  79.  
  80. //clean up leading spaces
  81. while(string_char_at(xml,1)==" "){
  82. xml = string_delete(xml,1,1);
  83. }
  84. while(string_pos(chr(10)+" ",xml)){
  85. xml=string_replace_all(xml,chr(10)+" ",chr(10));
  86. }
  87. while(string_pos(chr(13)+" ",xml)){
  88. xml=string_replace_all(xml,chr(13)+" ",chr(13));
  89. }
  90.  
  91. //clean up double spaces
  92. while(string_pos(" ",xml)){
  93. xml=string_replace_all(xml," "," ");
  94. }
  95.  
  96. // Set document (no parent = new document)
  97. if(parent == noone){
  98. document = xml_node_create(xml_document,"document",noone,self);
  99. parent = document;
  100. }else{
  101. document = parent.document;
  102. }
  103. buffer = xml;
  104. buffer_start = 0;
  105.  
  106. stack = ds_stack_create();
  107.  
  108. // read contents
  109.  
  110. while(str_find(buffer,"<")){
  111. buffer_start += str_find(buffer,"<");
  112. buffer = str_after(buffer,"<");
  113. type = xml_element; // DEFAULT = tag opening
  114. offset = 0;
  115. closing = false;
  116. cdata = "";
  117. comments = 0;
  118.  
  119. switch(string_char_at(buffer,1)){ // Check first character for special node_type
  120. case "!": // doctype declaration/definition
  121. type = xml_doctype;
  122. offset = 1;
  123. // filter out and capture cdata
  124. if(string_pos("[CDATA[",buffer)==1){
  125. cdata = str_between(buffer,"[CDATA[","]]");
  126. buffer_start += string_length(cdata)+9;
  127. buffer = str_outside(buffer,"[CDATA[","]]");
  128. }
  129. // filter out and capture comments
  130. while(str_is_first(buffer,"--",">")){
  131. comment[comments] = str_between(buffer,"--","--");
  132. buffer_start += string_length(comment[comments])+4;
  133. buffer = str_outside(buffer,"--","--");
  134. comments += 1;
  135. }
  136. break;
  137. case "?": // XML declaration
  138. type = xml_declaration;
  139. offset = 1;
  140. break;
  141. case "/": // tag closing
  142. closing = true;
  143. offset = 1;
  144. break;
  145. case " ": // whitespace offset
  146. offset = 1;
  147. break;
  148. }
  149.  
  150. // determine tag end position
  151. if(str_is_first(buffer,"/>",">")){
  152. tag_end = str_find(buffer,"/>");
  153. autoclose = true;
  154. }else{
  155. tag_end = str_find(buffer,">");
  156. autoclose = false;
  157. }
  158. // get name and attributes
  159. if(str_is_first(buffer," ",tag_end)){
  160. name = string_lower(str_between(buffer,offset," "));
  161. attrs = str_between(buffer," ",tag_end);
  162. }else{
  163. name = string_lower(str_between(buffer,offset,tag_end));
  164. attrs = "";
  165. }
  166.  
  167. // create or close the node
  168.  
  169. if(!closing){
  170. // create a node
  171.  
  172. node = xml_node_create(type,name,parent,document,attrs);
  173. node.opentag_start = buffer_start;
  174. node.opentag_end = buffer_start+tag_end;
  175. node.closetag_start = buffer_start;
  176. node.closetag_end = buffer_start+tag_end;
  177. node.inner_html = "";
  178. node.outer_html = "";
  179. if(type == xml_element && !autoclose){ // if it remains opened
  180. node.node_open = true;
  181. ds_stack_push(stack,node);
  182. parent = node;
  183. if(xml_debug>1)show_debug_message(
  184. "Pushing node #"+string(node)+" on stack."
  185. );
  186. }else{
  187. node.outer_html = str_between(xml,node.opentag_start-1,node.closetag_end+1);
  188. }
  189. if(type==xml_doctype){
  190. node.cdata = cdata;
  191. for(i=0;i<comments;i+=1){
  192. node.comment[i] = comment[i];
  193. }
  194. node.comments = comments;
  195. }
  196. if(xml_debug>1)show_debug_message(
  197. "Finished node: name = '"+name+
  198. "'; attrs = ["+attrs+"]; type = "+string(type)+
  199. "; open = "+string(node.node_open)+
  200. "; comments = "+string(comments)
  201. );
  202.  
  203.  
  204. }else{
  205. // close a node
  206.  
  207. /* Note:
  208. Variable "name" (name of currently closing tag) is only used to validate.
  209. The node that's actually closing is the one that was last opened.
  210. */
  211. node = ds_stack_pop(stack);
  212. if(!node){
  213. if(xml_debug>0)show_debug_message(
  214. "Malformed XML: closing "+name+" while no tags are open. "
  215. );
  216. continue;
  217. }
  218. parent = node.parent;
  219. if(name != node.node_name || !node.node_open){
  220. if(xml_debug>0)show_debug_message(
  221. "Malformed XML: closing "+name+" instead of "+node.node_name+". "
  222. );
  223. }
  224. // update node
  225. node.node_open = false;
  226. node.closetag_start = buffer_start;
  227. node.closetag_end = buffer_start+tag_end;
  228. node.inner_html = str_between(xml,node.opentag_end,node.closetag_start);
  229. node.outer_html = str_between(xml,node.opentag_start-1,node.closetag_end+1);
  230. if(xml_debug>1)show_debug_message(
  231. "Closing element node "+name+":
  232. from = " + string(node.opentag_start)+", " + string(node.opentag_end)+";
  233. to = " + string(node.closetag_start)+", " + string(node.closetag_end)
  234. );
  235. }
  236.  
  237. // make a textnode
  238.  
  239. txt = str_between(buffer,">","<"); // grab contents
  240. c = string_char_at(txt,1);
  241. while(c==" " || c==chr(10) || c==chr(13)){ // remove leading spaces and newlines
  242. txt = string_delete(txt,1,1);
  243. c = string_char_at(txt,1);
  244. }
  245. if(txt!=""){ // if not empty, make textnode
  246. text_node = xml_node_create(xml_text,"text",parent,document);
  247. text_node.node_value = txt;
  248. }
  249. }
  250. ds_stack_destroy(stack);
  251. return(document);
  252.  
  253. #define xml_node_create
  254. //xml_node_create(type:obj,name:str,parent:node,document:id,[attrs:str])
  255. var argument_num;if(!variable_local_exists('argument_count')){var a,i;a=0;for(i=0;i<16;i+=1){if(string(argument[i])!="0"){a=i+1;}}argument_num=a;}else{argument_num=argument_count;}
  256.  
  257. // Make a new node
  258.  
  259. var node,type,name,parent,document,attrs;
  260. type = argument0;
  261. name = argument1;
  262. parent = argument2;
  263. document = argument3;
  264. attrs = "";
  265. if(argument_num>4){
  266. attrs = argument[4];
  267. }
  268.  
  269. node = instance_create(0,0,type);
  270. node.parent = parent;
  271. node.document = document;
  272. node.node_name = name;
  273. node.node_type = type;
  274. node.child_id = 0;
  275. node.child_num = 0;
  276. node.node_open = false;
  277. node.attr_map = -1;
  278.  
  279. if(node.parent && instance_exists(node.parent)){
  280. node.parent.child_nodes[node.parent.child_num]=node;
  281. node.parent.child_num+=1;
  282.  
  283. node.child_id = node.parent.child_num;
  284.  
  285. if(xml_debug>1)show_debug_message(
  286. "Created node "+string(node)+":
  287. name="+name+";
  288. type="+string(type)+";
  289. parent="+string(parent)+";
  290. child_id="+string(node.child_id)+";
  291. attrs="+string(attrs)
  292. );
  293. }
  294. if(type==xml_element && attrs!=""){
  295. xml_set_attributes(node,attrs);
  296. }
  297. if(type==xml_doctype){
  298. node.doctype_attrs = attrs;
  299. }
  300. return(node);
  301.  
  302. #define xml_set_attributes
  303. //xml_set_attributes(node:id,attributes:str)
  304.  
  305. // Convert a string with attributes to node variables
  306.  
  307. var node,attr,buffer,attrname,attrval,quote;
  308. node = argument0;
  309. attr = argument1+" ";
  310. buffer = attr;
  311.  
  312. /*
  313. if(node.attr_map < 0){
  314. node.attr_map = ds_map_create();
  315. }
  316. */
  317.  
  318. do{
  319. // skip leading whitespaces
  320. while(string_char_at(buffer,0)==" "){
  321. buffer = string_delete(buffer,1,1);
  322. }
  323. // get attribute name
  324. if(str_is_first(buffer," ","=")){
  325. attrname = str_before(buffer," ");
  326. buffer = str_after(buffer," ");
  327. has_value = false;
  328. }else{
  329. attrname = str_before(buffer,"=");
  330. buffer = str_after(buffer,"=");
  331. has_value = true;
  332. }
  333. // get attribute value
  334. quote = '"';
  335. if(attrname!="" && attrname!=" " && attrname!="/"){
  336. quote = str_first(buffer,"'",'"'); // determine quote type
  337. if(str_is_first(buffer,quote," ")){
  338. attrval = str_between_ext(buffer,quote,quote,0,true,false); // _ext version to allow escaped quotes
  339. buffer = str_after_ext(buffer,quote,quote,true);
  340. }else{
  341. if(has_value){
  342. attrval = str_before(buffer," ")
  343. }else{
  344. attrval = "";
  345. }
  346. buffer = str_after(buffer," ");
  347. }
  348. with(node){
  349. variable_local_set("attr_"+attrname,attrval);
  350. //ds_map_set(attr_map,attrname,attrval);
  351. if(xml_debug>1)show_debug_message(" - var_set(attr_"+attrname+","+attrval+")");
  352. }
  353. }
  354. //if(!show_question("buffer: "+buffer+"##name: "+attrname+"#val: "+attrval)){return(0)};
  355. }until(!str_find(buffer," "));
  356.  
  357. #define xml_get_attribute
  358. //xml_get_attribute(element:id,attribute:str)
  359. var element,attr;
  360. element = argument0;
  361. attr = argument1;
  362.  
  363. with(element){
  364. return(var_get("attr_"+attr));
  365. }
  366.  
  367. #define xml_element_select
  368. //xml_element_select(attribute:str,value:str/real,[num:real])
  369. var argument_num;if(!variable_local_exists('argument_count')){var a,i;a=0;for(i=0;i<16;i+=1){if(string(argument[i])!="0"){a=i+1;}}argument_num=a;}else{argument_num=argument_count;}
  370.  
  371. var attr,val,num,i;
  372. attr = argument0;
  373. val = argument1;
  374. num = 1;
  375. if(argument_num>2){
  376. num = max(1,argument[2]);
  377. }
  378. i=0;
  379. with(xml_element){
  380. if(var_get("attr_"+attr)==val){
  381. i+=1;
  382. if(i==num){
  383. return(id);
  384. }
  385. }
  386. }
  387. return(false);
  388.  
  389. #define xml_element_search
  390. //xml_element_search(attribute:str,needle:str,[num:real])
  391. var argument_num;if(!variable_local_exists('argument_count')){var a,i;a=0;for(i=0;i<16;i+=1){if(string(argument[i])!="0"){a=i+1;}}argument_num=a;}else{argument_num=argument_count;}
  392.  
  393. var attr,val,num,i;
  394. attr = argument0;
  395. val = argument1;
  396. num = 1;
  397. if(argument_num>2){
  398. num = max(1,argument[2]);
  399. }
  400. i=0;
  401. with(xml_element){
  402. if(string_pos(val,var_get("attr_"+attr))){
  403. i+=1;
  404. if(i==num){
  405. return(id);
  406. }
  407. }
  408. }
  409. return(false);
  410.  
  411. #define xml_is_ancestor
  412. //xml_is_ancestor(node:id,ancestor:id/str)
  413. var node,ancestor;
  414. node = argument0;
  415. ancestor = argument1;
  416.  
  417. with(node){
  418. if(var_is_local("parent")){
  419. if(is_string(ancestor)){
  420. if(node_name==ancestor){
  421. return(true);
  422. }
  423. }else{
  424. if(parent==ancestor){
  425. return(true);
  426. }
  427. }
  428. return(xml_is_ancestor(parent,ancestor));
  429. }
  430. }
  431. return(false);
  432.  
  433. #define xml_find_ancestor
  434. //xml_find_ancestor(node:id,ancestor:str)
  435. var node,ancestor;
  436. node = argument0;
  437. ancestor = argument1;
  438. with(node){
  439. if(node_name==ancestor){
  440. return(node);
  441. }else{
  442. return(xml_find_ancestor(parent,ancestor));
  443. }
  444. }
  445. return(true);
Add Comment
Please, Sign In to add comment