superxmlparser.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  1. (*
  2. * Super Object Toolkit
  3. *
  4. * Usage allowed under the restrictions of the Lesser GNU General Public License
  5. * or alternatively the restrictions of the Mozilla Public License 1.1
  6. *
  7. * Software distributed under the License is distributed on an "AS IS" basis,
  8. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  9. * the specific language governing rights and limitations under the License.
  10. *
  11. * Embarcadero Technologies Inc is not permitted to use or redistribute
  12. * this source code without explicit permission.
  13. *
  14. * Unit owner : Henri Gourvest <hgourvest@gmail.com>
  15. * Web site : http://www.progdigy.com
  16. *)
  17. unit superxmlparser;
  18. {$IFDEF FPC}
  19. {$MODE OBJFPC}{$H+}
  20. {$ENDIF}
  21. interface
  22. uses superobject, classes;
  23. type
  24. TOnProcessingInstruction = procedure(const PI, PIParent: ISuperObject);
  25. function XMLParseString(const data: SOString; pack: Boolean = false; onpi: TOnProcessingInstruction = nil): ISuperObject;
  26. function XMLParseStream(stream: TStream; pack: Boolean = false; onpi: TOnProcessingInstruction = nil): ISuperObject;
  27. function XMLParseFile(const FileName: string; pack: Boolean = false; onpi: TOnProcessingInstruction = nil): ISuperObject;
  28. {$IFDEF UNICODE}
  29. type
  30. TXMLWriteMethod = reference to procedure(const data: string);
  31. procedure XMLWrite(const node: ISuperObject; const method: TXMLWriteMethod);
  32. {$ENDIF}
  33. const
  34. xmlname = '#name';
  35. xmlattributes = '#attributes';
  36. xmlchildren = '#children';
  37. xmltext = '#text';
  38. dtdname = '#name';
  39. dtdPubidLiteral = '#pubidliteral';
  40. dtdSystemLiteral = '#systemliteral';
  41. implementation
  42. uses sysutils {$IFNDEF UNIX}, windows{$ENDIF};
  43. const
  44. XML_SPACE : PSOChar = #32;
  45. // XML_ARL: PSOChar = '[';
  46. XML_ARR: PSOChar = ']';
  47. XML_BIG: PSOChar = '>';
  48. XML_LOW: PSOChar = '<';
  49. XML_AMP: PSOChar = '&';
  50. XML_SQU: PSOChar = '''';
  51. XML_DQU: PSOChar = '"';
  52. type
  53. TSuperXMLState = (
  54. xsStart, // |
  55. xsEatSpaces, //
  56. xsElement, // <|
  57. xsElementName, // <[a..z]|
  58. xsAttributes, // <xml |
  59. xsAttributeName, // <xml a|
  60. xsEqual, // |= ...
  61. xsAttributeValue, // = |"...
  62. xsCloseEmptyElement, // <xml/|
  63. xsTryCloseElement, // <xml>..<|
  64. xsCloseElementName, // <xml>..</|
  65. xsChildren, // <xml>|
  66. xsElementString, // <xml> |azer
  67. xsElementComment, // <!|-- ...
  68. xsElementDocType, // <!D|
  69. xsElementDocTypeName, // <!DOCTYPE |...
  70. xsElementDocTypeExternId, // <!DOCTYPE xml |
  71. xsElementDocTypeExternIdPublic, // <!DOCTYPE xml P|
  72. xsElementDocTypeExternIdSystem, // <!DOCTYPE xml S|
  73. xsElementDocTypePubIdLiteral, // <!DOCTYPE xml SYSTEM |"
  74. xsElementDocTypeSystemLiteral, // <!DOCTYPE xml SYSTEM "" |""
  75. xsElementDocTypeTryIntSubset,
  76. xsElementDocTypeIntSubset,
  77. xsElementDocTypeTryClose,
  78. xsElementDocTypeEat, //
  79. xsCloseElementComment, // <!-- -|->
  80. xsElementPI, // <?|
  81. xsElementDataPI, // not an xml PI
  82. xsCloseElementPI, // <? ?|>
  83. xsElementCDATA, // <![|CDATA[
  84. xsClodeElementCDATA, // ]|]>
  85. xsEscape, // &|
  86. xsEscape_lt, // &l|t;
  87. xsEscape_gt, // &g|t;
  88. xsEscape_amp, // &a|mp;
  89. xsEscape_apos, // &a|pos;
  90. xsEscape_quot, // &q|uot;
  91. xsEscape_char, // &#|;
  92. xsEscape_char_num, // &#1|123456;
  93. xsEscape_char_hex, // &#x|000FFff;
  94. xsEnd);
  95. TSuperXMLError = (xeSuccess, xeContinue, xeProcessInst, xeError);
  96. TSuperXMLElementClass = (xcNone, xcElement, xcComment, xcString, xcCdata, xcDocType, xcProcessInst);
  97. TSuperXMLEncoding = ({$IFNDEF UNIX}xnANSI,{$ENDIF} xnUTF8, xnUnicode);
  98. {$IFDEF UNICODE}
  99. procedure XMLWrite(const node: ISuperObject; const method: TXMLWriteMethod);
  100. var
  101. o: ISuperObject;
  102. ent: TSuperAvlEntry;
  103. str: string;
  104. begin
  105. str := '<' + node.S[xmlname];
  106. if ObjectIsType(node[xmlattributes], stObject) then
  107. for ent in node[xmlattributes].AsObject do
  108. str := str + ' ' + ent.Name + '="' + ent.Value.AsString + '"';
  109. if ObjectIsType(node[xmlchildren], stArray) then
  110. begin
  111. method(str + '>');
  112. for o in node[xmlchildren] do
  113. if ObjectIsType(o, stString) then
  114. method(o.AsString) else
  115. XMLWrite(o, method);
  116. method('</' + node.S[xmlname] + '>');
  117. end else
  118. method(str + '/>');
  119. end;
  120. {$ENDIF}
  121. type
  122. PSuperXMLStack = ^TSuperXMLStack;
  123. TSuperXMLStack = record
  124. state: TSuperXMLState;
  125. savedstate: TSuperXMLState;
  126. prev: PSuperXMLStack;
  127. next: PSuperXMLStack;
  128. clazz: TSuperXMLElementClass;
  129. obj: ISuperObject;
  130. end;
  131. TSuperXMLParser = class
  132. private
  133. FStack: PSuperXMLStack;
  134. FDocType: ISuperObject;
  135. FError: TSuperXMLError;
  136. FStr: TSuperWriterString;
  137. FValue: TSuperWriterString;
  138. FPosition: Integer;
  139. FAChar: SOChar;
  140. FPack: Boolean;
  141. procedure StackUp;
  142. procedure StackDown;
  143. procedure Reset;
  144. function ParseBuffer(data: PSOChar; var PI, PIParent: ISuperObject; len: Integer = -1): Integer;
  145. public
  146. constructor Create(pack: Boolean);
  147. destructor Destroy; override;
  148. end;
  149. { TXMLContext }
  150. constructor TSuperXMLParser.Create(pack: Boolean);
  151. begin
  152. FDocType := nil;
  153. FStr := TSuperWriterString.Create;
  154. FValue := TSuperWriterString.Create;
  155. StackUp;
  156. FError := xeSuccess;
  157. FPack := pack;
  158. end;
  159. destructor TSuperXMLParser.Destroy;
  160. begin
  161. while FStack <> nil do
  162. StackDown;
  163. FStr.Free;
  164. FValue.Free;
  165. end;
  166. procedure TSuperXMLParser.Reset;
  167. begin
  168. while FStack <> nil do
  169. StackDown;
  170. StackUp;
  171. FError := xeSuccess;
  172. end;
  173. function TSuperXMLParser.ParseBuffer(data: PSOChar; var PI, PIParent: ISuperObject; len: integer): Integer;
  174. const
  175. spaces = [#32,#9,#10,#13];
  176. alphas = ['a'..'z', 'A'..'Z', '_', ':', #161..#255];
  177. nums = ['0'..'9', '.', '-'];
  178. hex = nums + ['a'..'f','A'..'F'];
  179. alphanums = alphas + nums;
  180. publitteral = [#32, #13, #10, 'a'..'z', 'A'..'Z', '0'..'9', '-', '''', '"', '(', ')',
  181. '+', ',', '.', '/', ':', '=', '?', ';', '!', '*', '#', '@', '$', '_', '%'];
  182. function hexdigit(const x: SOChar): byte;
  183. begin
  184. if x <= '9' then
  185. Result := byte(x) - byte('0') else
  186. Result := (byte(x) and 7) + 9;
  187. end;
  188. procedure putchildrenstr;
  189. var
  190. anobject: ISuperObject;
  191. begin
  192. anobject := FStack^.obj.AsObject[xmlchildren];
  193. if anobject = nil then
  194. begin
  195. anobject := TSuperObject.Create(stArray);
  196. FStack^.obj.AsObject[xmlchildren] := anobject;
  197. end;
  198. anobject.AsArray.Add(TSuperObject.Create(FValue.Data));
  199. end;
  200. procedure AddProperty(const parent, value: ISuperObject; const name: SOString);
  201. var
  202. anobject: ISuperObject;
  203. arr: ISuperObject;
  204. begin
  205. anobject := parent.AsObject[name];
  206. if anobject = nil then
  207. parent.AsObject[name] := value else
  208. begin
  209. if (anobject.DataType = stArray) then
  210. anobject.AsArray.Add(value) else
  211. begin
  212. arr := TSuperObject.Create(stArray);
  213. arr.AsArray.Add(anobject);
  214. arr.AsArray.Add(value);
  215. parent.AsObject[name] := arr;
  216. end;
  217. end;
  218. end;
  219. procedure packend;
  220. var
  221. anobject, anobject2: ISuperObject;
  222. n: Integer;
  223. begin
  224. anobject := FStack^.obj.AsObject[xmlchildren];
  225. if (anobject <> nil) and (anobject.AsArray.Length = 1) and (anobject.AsArray[0].DataType = stString) then
  226. begin
  227. if FStack^.obj.AsObject.count = 2 then // name + children
  228. begin
  229. if FStack^.prev <> nil then
  230. AddProperty(FStack^.prev^.obj, anobject.AsArray[0], FStack^.obj.AsObject.S[xmlname]) else
  231. begin
  232. AddProperty(FStack^.obj, anobject.AsArray[0], xmltext);
  233. FStack^.obj.AsObject.Delete(xmlchildren);
  234. end;
  235. end
  236. else
  237. begin
  238. AddProperty(FStack^.obj, anobject.AsArray[0], FStack^.obj.AsObject.S[xmlname]);
  239. FStack^.obj.AsObject.Delete(xmlchildren);
  240. if FStack^.prev <> nil then
  241. AddProperty(FStack^.prev^.obj, FStack^.obj, FStack^.obj.AsObject.S[xmlname]) else
  242. FStack^.obj.AsObject.Delete(xmlchildren);
  243. FStack^.obj.AsObject.Delete(xmlname);
  244. end;
  245. end else
  246. begin
  247. if (anobject <> nil) then
  248. begin
  249. for n := 0 to anobject.AsArray.Length - 1 do
  250. begin
  251. anobject2 := anobject.AsArray[n];
  252. if ObjectIsType(anobject2, stObject) then
  253. begin
  254. AddProperty(FStack^.obj, anobject2, anobject2.AsObject.S[xmlname]);
  255. anobject2.AsObject.Delete(xmlname);
  256. end else
  257. AddProperty(FStack^.obj, anobject2, xmltext);
  258. end;
  259. FStack^.obj.Delete(xmlchildren);
  260. end;
  261. if (FStack^.prev <> nil) and (FStack^.obj.AsObject.count > 1) then
  262. begin
  263. if (FStack^.obj.AsObject.count = 2) and (FStack^.obj.AsObject[xmltext] <> nil) then
  264. AddProperty(FStack^.prev^.obj, FStack^.obj.AsObject[xmltext], FStack^.obj.AsObject.S[xmlname]) else
  265. AddProperty(FStack^.prev^.obj, FStack^.obj, FStack^.obj.AsObject.S[xmlname]);
  266. end;
  267. FStack^.obj.Delete(xmlname);
  268. end;
  269. end;
  270. var
  271. c: SOChar;
  272. read: Integer;
  273. p: PSOChar;
  274. anobject: ISuperObject;
  275. label
  276. redo, err;
  277. begin
  278. p := data;
  279. read := 0;
  280. //Result := 0;
  281. repeat
  282. if (read = len) then
  283. begin
  284. if (FStack^.prev = nil) and ((FStack^.state = xsEnd) or ((FStack^.state = xsEatSpaces) and (FStack^.savedstate = xsEnd))) then
  285. begin
  286. if FPack then
  287. packend;
  288. FError := xeSuccess;
  289. end else
  290. FError := xeContinue;
  291. Result := read;
  292. exit;
  293. end;
  294. c := p^;
  295. redo:
  296. case FStack^.state of
  297. xsEatSpaces:
  298. if {$IFDEF UNICODE}(c < #256) and {$ENDIF} (AnsiChar(c) in spaces) then {nop} else
  299. begin
  300. FStack^.state := FStack^.savedstate;
  301. goto redo;
  302. end;
  303. xsStart:
  304. case c of
  305. '<': FStack^.state := xsElement;
  306. else
  307. goto err;
  308. end;
  309. xsElement:
  310. begin
  311. case c of
  312. '?':
  313. begin
  314. FStack^.savedstate := xsStart;
  315. FStack^.state := xsEatSpaces;
  316. StackUp;
  317. FStr.Reset;
  318. FStack^.state := xsElementPI;
  319. FStack^.clazz := xcProcessInst;
  320. end;
  321. '!':
  322. begin
  323. FPosition := 0;
  324. FStack^.state := xsElementComment;
  325. FStack^.clazz := xcComment;
  326. end;
  327. else
  328. if ((c < #256) and (AnsiChar(c) in alphas)) or (c >= #256) then
  329. begin
  330. FStr.Reset;
  331. FStack^.state := xsElementName;
  332. FStack^.clazz := xcElement;
  333. goto redo;
  334. end else
  335. goto err;
  336. end;
  337. end;
  338. xsElementPI:
  339. begin
  340. if ((c < #256) and (AnsiChar(c) in alphanums)) or (c >= #256) then
  341. FStr.Append(@c, 1) else
  342. begin
  343. FStack^.obj := TSuperObject.Create(stObject);
  344. FStack^.obj.AsObject.S[xmlname] := FStr.Data;
  345. FStack^.state := xsEatSpaces;
  346. if FStr.Data = 'xml' then
  347. FStack^.savedstate := xsAttributes else
  348. begin
  349. FValue.Reset;
  350. FStack^.savedstate := xsElementDataPI;
  351. end;
  352. goto redo;
  353. end;
  354. end;
  355. xsElementDataPI:
  356. begin
  357. case c of
  358. '?':
  359. begin
  360. FStack^.obj.AsObject.S['data'] := FValue.Data;
  361. FStack^.state := xsCloseElementPI;
  362. end;
  363. else
  364. FValue.Append(@c, 1);
  365. end;
  366. end;
  367. xsCloseElementPI:
  368. begin
  369. if (c <> '>') then goto err;
  370. PI := FStack^.obj;
  371. StackDown;
  372. PIParent := FStack^.obj;
  373. FError := xeProcessInst;
  374. Result := read + 1;
  375. Exit;
  376. end;
  377. xsElementName:
  378. begin
  379. if ((c < #256) and (AnsiChar(c) in alphanums)) or (c >= #256) then
  380. FStr.Append(@c, 1) else
  381. begin
  382. FStack^.obj := TSuperObject.Create(stObject);
  383. FStack^.obj.AsObject.S[xmlname] := FStr.Data;
  384. FStack^.state := xsEatSpaces;
  385. FStack^.savedstate := xsAttributes;
  386. goto redo;
  387. end;
  388. end;
  389. xsChildren:
  390. begin
  391. case c of
  392. '<': FStack^.state := xsTryCloseElement;
  393. else
  394. FValue.Reset;
  395. FStack^.state := xsElementString;
  396. FStack^.clazz := xcString;
  397. goto redo;
  398. end;
  399. end;
  400. xsCloseEmptyElement:
  401. begin
  402. case c of
  403. '>':
  404. begin
  405. FStack^.state := xsEatSpaces;
  406. FStack^.savedstate := xsEnd;
  407. end
  408. else
  409. goto err;
  410. end;
  411. end;
  412. xsTryCloseElement:
  413. begin
  414. case c of
  415. '/': begin
  416. FStack^.state := xsCloseElementName;
  417. FPosition := 0;
  418. FStr.Reset;
  419. FStr.Append(PSoChar(FStack^.obj.AsObject.S[xmlname]));
  420. end;
  421. '!': begin
  422. FPosition := 0;
  423. FStack^.state := xsElementComment;
  424. FStack^.clazz := xcComment;
  425. end;
  426. '?': begin
  427. FStack^.savedstate := xsChildren;
  428. FStack^.state := xsEatSpaces;
  429. StackUp;
  430. FStr.Reset;
  431. FStack^.state := xsElementPI;
  432. FStack^.clazz := xcProcessInst;
  433. end
  434. else
  435. FStack^.state := xsChildren;
  436. StackUp;
  437. if ((c < #256) and (AnsiChar(c) in alphas)) or (c >= #256) then
  438. begin
  439. FStr.Reset;
  440. FStack^.state := xsElementName;
  441. FStack^.clazz := xcElement;
  442. goto redo;
  443. end else
  444. goto err;
  445. end;
  446. end;
  447. xsCloseElementName:
  448. begin
  449. if FStr.Position = FPosition then
  450. begin
  451. FStack^.savedstate := xsCloseEmptyElement;
  452. FStack^.state := xsEatSpaces;
  453. goto redo;
  454. end else
  455. begin
  456. if (c <> FStr.Data[FPosition]) then goto err;
  457. inc(FPosition);
  458. end;
  459. end;
  460. xsAttributes:
  461. begin
  462. case c of
  463. '?': begin
  464. if FStack^.clazz <> xcProcessInst then goto err;
  465. FStack^.state := xsCloseElementPI;
  466. end;
  467. '/': begin
  468. FStack^.state := xsCloseEmptyElement;
  469. end;
  470. '>': begin
  471. FStack^.state := xsEatSpaces;
  472. FStack^.savedstate := xsChildren;
  473. end
  474. else
  475. if ((c < #256) and (AnsiChar(c) in alphas)) or (c >= #256) then
  476. begin
  477. FStr.Reset;
  478. FStr.Append(@c, 1);
  479. FStack^.state := xsAttributeName;
  480. end else
  481. goto err;
  482. end;
  483. end;
  484. xsAttributeName:
  485. begin
  486. if ((c < #256) and (AnsiChar(c) in alphanums)) or (c >= #256) then
  487. FStr.Append(@c, 1) else
  488. begin
  489. // no duplicate attribute
  490. if FPack then
  491. begin
  492. if FStack^.obj.AsObject[FStr.Data] <> nil then
  493. goto err;
  494. end else
  495. begin
  496. anobject := FStack^.obj.AsObject[xmlattributes];
  497. if (anobject <> nil) and (anobject.AsObject[FStr.Data] <> nil) then
  498. goto err;
  499. end;
  500. FStack^.state := xsEatSpaces;
  501. FStack^.savedstate := xsEqual;
  502. goto redo;
  503. end;
  504. end;
  505. xsEqual:
  506. begin
  507. if c <> '=' then goto err;
  508. FStack^.state := xsEatSpaces;
  509. FStack^.savedstate := xsAttributeValue;
  510. FValue.Reset;
  511. FPosition := 0;
  512. FAChar := #0;
  513. end;
  514. xsAttributeValue:
  515. begin
  516. if FAChar <> #0 then
  517. begin
  518. if (c = FAChar) then
  519. begin
  520. if FPack then
  521. begin
  522. FStack^.obj.AsObject[FStr.Data] := TSuperObject.Create(Fvalue.Data);
  523. end else
  524. begin
  525. anobject := FStack^.obj.AsObject[xmlattributes];
  526. if anobject = nil then
  527. begin
  528. anobject := TSuperObject.Create(stObject);
  529. FStack^.obj.AsObject[xmlattributes] := anobject;
  530. end;
  531. anobject.AsObject[FStr.Data] := TSuperObject.Create(Fvalue.Data);
  532. end;
  533. FStack^.savedstate := xsAttributes;
  534. FStack^.state := xsEatSpaces;
  535. end else
  536. case c of
  537. '&':
  538. begin
  539. FStack^.state := xsEscape;
  540. FStack^.savedstate := xsAttributeValue;
  541. end;
  542. #13, #10:
  543. begin
  544. FValue.TrimRight;
  545. FValue.Append(XML_SPACE, 1);
  546. FStack^.state := xsEatSpaces;
  547. FStack^.savedstate := xsAttributeValue;
  548. end;
  549. else
  550. FValue.Append(@c, 1);
  551. end;
  552. end else
  553. begin
  554. if (c < #256) and (AnsiChar(c) in ['"', '''']) then
  555. begin
  556. FAChar := c;
  557. inc(FPosition);
  558. end else
  559. goto err;
  560. end;
  561. end;
  562. xsElementString:
  563. begin
  564. case c of
  565. '<': begin
  566. FValue.TrimRight;
  567. putchildrenstr;
  568. FStack^.state := xsTryCloseElement;
  569. end;
  570. #13, #10:
  571. begin
  572. FValue.TrimRight;
  573. FValue.Append(XML_SPACE, 1);
  574. FStack^.state := xsEatSpaces;
  575. FStack^.savedstate := xsElementString;
  576. end;
  577. '&':
  578. begin
  579. FStack^.state := xsEscape;
  580. FStack^.savedstate := xsElementString;
  581. end
  582. else
  583. FValue.Append(@c, 1);
  584. end;
  585. end;
  586. xsElementComment:
  587. begin
  588. case FPosition of
  589. 0:
  590. begin
  591. case c of
  592. '-': Inc(FPosition);
  593. '[':
  594. begin
  595. FValue.Reset;
  596. FPosition := 0;
  597. FStack^.state := xsElementCDATA;
  598. FStack^.clazz := xcCdata;
  599. end;
  600. 'D':
  601. begin
  602. if (FStack^.prev = nil) and (FDocType = nil) then
  603. begin
  604. FStack^.state := xsElementDocType;
  605. FPosition := 0;
  606. FStack^.clazz := xcDocType;
  607. end else
  608. goto err;
  609. end;
  610. else
  611. goto err;
  612. end;
  613. end;
  614. 1:
  615. begin
  616. if c <> '-' then goto err;
  617. Inc(FPosition);
  618. end;
  619. else
  620. if c = '-' then
  621. begin
  622. FPosition := 0;
  623. FStack^.state := xsCloseElementComment;
  624. end;
  625. end;
  626. end;
  627. xsCloseElementComment:
  628. begin
  629. case FPosition of
  630. 0: begin
  631. if c <> '-' then
  632. begin
  633. FPosition := 2;
  634. FStack^.state := xsElementComment;
  635. end else
  636. Inc(FPosition);
  637. end;
  638. 1: begin
  639. if c <> '>' then goto err;
  640. FStack^.state := xsEatSpaces;
  641. if FStack^.obj <> nil then
  642. FStack^.savedstate := xsChildren else
  643. FStack^.savedstate := xsStart;
  644. end;
  645. end;
  646. end;
  647. xsElementCDATA:
  648. begin
  649. case FPosition of
  650. 0: if (c = 'C') then inc(FPosition) else goto err;
  651. 1: if (c = 'D') then inc(FPosition) else goto err;
  652. 2: if (c = 'A') then inc(FPosition) else goto err;
  653. 3: if (c = 'T') then inc(FPosition) else goto err;
  654. 4: if (c = 'A') then inc(FPosition) else goto err;
  655. 5: if (c = '[') then inc(FPosition) else goto err;
  656. else
  657. case c of
  658. ']': begin
  659. FPosition := 0;
  660. FStack^.state := xsClodeElementCDATA;
  661. end;
  662. else
  663. FValue.Append(@c, 1);
  664. end;
  665. end;
  666. end;
  667. xsClodeElementCDATA:
  668. begin
  669. case FPosition of
  670. 0: if (c = ']') then
  671. inc(FPosition) else
  672. begin
  673. FValue.Append(XML_ARR, 1);
  674. FValue.Append(@c, 1);
  675. FPosition := 6;
  676. FStack^.state := xsElementCDATA;
  677. end;
  678. 1: case c of
  679. '>':
  680. begin
  681. putchildrenstr;
  682. FStack^.state := xsEatSpaces;
  683. FStack^.savedstate := xsChildren;
  684. end;
  685. ']':
  686. begin
  687. FValue.Append(@c, 1);
  688. end;
  689. else
  690. FValue.Append(@c, 1);
  691. FStack^.state := xsElementCDATA;
  692. end;
  693. end;
  694. end;
  695. xsElementDocType:
  696. begin
  697. case FPosition of
  698. 0: if (c = 'O') then inc(FPosition) else goto err;
  699. 1: if (c = 'C') then inc(FPosition) else goto err;
  700. 2: if (c = 'T') then inc(FPosition) else goto err;
  701. 3: if (c = 'Y') then inc(FPosition) else goto err;
  702. 4: if (c = 'P') then inc(FPosition) else goto err;
  703. 5: if (c = 'E') then inc(FPosition) else goto err;
  704. else
  705. if (c < #256) and (AnsiChar(c) in spaces) then
  706. begin
  707. FStack^.state := xsEatSpaces;
  708. FStack^.savedstate := xsElementDocTypeName;
  709. FStr.Reset;
  710. end else
  711. goto err;
  712. end;
  713. end;
  714. xsElementDocTypeName:
  715. begin
  716. case FStr.Position of
  717. 0: begin
  718. case c of
  719. '>':
  720. begin
  721. FStack^.state := xsEatSpaces;
  722. FStack^.state := xsStart;
  723. FStack^.clazz := xcNone;
  724. end
  725. else
  726. if ((c < #256) and (AnsiChar(c) in alphas)) or (c > #256) then
  727. FStr.Append(@c, 1) else
  728. goto err;
  729. end;
  730. end;
  731. else
  732. if ((c < #256) and (AnsiChar(c) in alphanums)) or (c > #256) then
  733. FStr.Append(@c, 1) else
  734. if (c < #256) and (AnsiChar(c) in spaces) then
  735. begin
  736. FDocType := TSuperObject.Create(stObject);
  737. FDocType.AsObject.S[xmlname] := FStr.Data;
  738. FStack^.state := xsEatSpaces;
  739. FStack^.savedstate := xsElementDocTypeExternId;
  740. end else
  741. goto err;
  742. end;
  743. end;
  744. xsElementDocTypeExternId:
  745. begin
  746. case c of
  747. 'P':
  748. begin
  749. FPosition := 0;
  750. FStack^.state := xsElementDocTypeExternIdPublic;
  751. end;
  752. 'S':
  753. begin
  754. FPosition := 0;
  755. FStack^.state := xsElementDocTypeExternIdSystem;
  756. end;
  757. '[':
  758. begin
  759. FStack^.savedstate := xsElementDocTypeIntSubset;
  760. FStack^.state := xsEatSpaces;
  761. end;
  762. '>':
  763. begin
  764. FStack^.savedstate := xsStart;
  765. FStack^.state := xsEatSpaces
  766. end
  767. else
  768. goto err;
  769. end;
  770. end;
  771. xsElementDocTypeExternIdPublic:
  772. begin
  773. case FPosition of
  774. 0: if (c = 'U') then inc(FPosition) else goto err;
  775. 1: if (c = 'B') then inc(FPosition) else goto err;
  776. 2: if (c = 'L') then inc(FPosition) else goto err;
  777. 3: if (c = 'I') then inc(FPosition) else goto err;
  778. 4: if (c = 'C') then inc(FPosition) else goto err;
  779. else
  780. if (c < #256) and (AnsiChar(c) in spaces) then
  781. begin
  782. FStr.Reset;
  783. FPosition := 0;
  784. FStack^.savedstate := xsElementDocTypePubIdLiteral;
  785. FStack^.state := xsEatSpaces;
  786. end else
  787. goto err;
  788. end;
  789. end;
  790. xsElementDocTypeExternIdSystem:
  791. begin
  792. case FPosition of
  793. 0: if (c = 'Y') then inc(FPosition) else goto err;
  794. 1: if (c = 'S') then inc(FPosition) else goto err;
  795. 2: if (c = 'T') then inc(FPosition) else goto err;
  796. 3: if (c = 'E') then inc(FPosition) else goto err;
  797. 4: if (c = 'M') then inc(FPosition) else goto err;
  798. else
  799. if (c < #256) and (AnsiChar(c) in spaces) then
  800. begin
  801. FStr.Reset;
  802. FPosition := 0;
  803. FStack^.savedstate := xsElementDocTypeSystemLiteral;
  804. FStack^.state := xsEatSpaces;
  805. end else
  806. goto err;
  807. end;
  808. end;
  809. xsElementDocTypePubIdLiteral:
  810. begin
  811. if FPosition = 0 then
  812. case c of
  813. '"', '''':
  814. begin
  815. FAChar := c;
  816. FPosition := 1;
  817. end
  818. else
  819. goto err;
  820. end else
  821. if c = FAChar then
  822. begin
  823. FDocType.AsObject.S[dtdPubidLiteral] := FStr.Data;
  824. FStr.Reset;
  825. FPosition := 0;
  826. FStack^.state := xsEatSpaces;
  827. FStack^.savedstate := xsElementDocTypeSystemLiteral;
  828. end else
  829. if (c < #256) and (AnsiChar(c) in publitteral) then
  830. FStr.Append(@c, 1);
  831. end;
  832. xsElementDocTypeSystemLiteral:
  833. begin
  834. if FPosition = 0 then
  835. case c of
  836. '"', '''':
  837. begin
  838. FAChar := c;
  839. FPosition := 1;
  840. end
  841. else
  842. goto err;
  843. end else
  844. if c = FAChar then
  845. begin
  846. FDocType.AsObject.S[dtdSystemLiteral] := FStr.Data;
  847. FStack^.state := xsEatSpaces;
  848. FStack^.savedstate := xsElementDocTypeTryIntSubset;
  849. end else
  850. FStr.Append(@c, 1);
  851. end;
  852. xsElementDocTypeTryIntSubset:
  853. begin
  854. case c of
  855. '>':
  856. begin
  857. FStack^.state := xsEatSpaces;
  858. FStack^.savedstate := xsStart;
  859. FStack^.clazz := xcNone;
  860. end;
  861. '[':
  862. begin
  863. FStack^.state := xsEatSpaces;
  864. FStack^.savedstate := xsElementDocTypeIntSubset;
  865. end;
  866. end;
  867. end;
  868. xsElementDocTypeIntSubset:
  869. begin
  870. case c of
  871. ']':
  872. begin
  873. FStack^.state := xsEatSpaces;
  874. FStack^.savedstate := xsElementDocTypeTryClose;
  875. end;
  876. end;
  877. end;
  878. xsElementDocTypeTryClose:
  879. begin
  880. if c = '>' then
  881. begin
  882. FStack^.state := xsEatSpaces;
  883. FStack^.savedstate := xsStart;
  884. FStack^.clazz := xcNone;
  885. end else
  886. goto err;
  887. end;
  888. xsEscape:
  889. begin
  890. FPosition := 0;
  891. case c of
  892. 'l': FStack^.state := xsEscape_lt;
  893. 'g': FStack^.state := xsEscape_gt;
  894. 'a': FStack^.state := xsEscape_amp;
  895. 'q': FStack^.state := xsEscape_quot;
  896. '#': FStack^.state := xsEscape_char;
  897. else
  898. goto err;
  899. end;
  900. end;
  901. xsEscape_lt:
  902. begin
  903. case FPosition of
  904. 0: begin
  905. if c <> 't' then goto err;
  906. Inc(FPosition);
  907. end;
  908. 1: begin
  909. if c <> ';' then goto err;
  910. FValue.Append(XML_LOW, 1);
  911. FStack^.state := FStack^.savedstate;
  912. end;
  913. end;
  914. end;
  915. xsEscape_gt:
  916. begin
  917. case FPosition of
  918. 0: begin
  919. if c <> 't' then goto err;
  920. Inc(FPosition);
  921. end;
  922. 1: begin
  923. if c <> ';' then goto err;
  924. FValue.Append(XML_BIG, 1);
  925. FStack^.state := FStack^.savedstate;
  926. end;
  927. end;
  928. end;
  929. xsEscape_amp:
  930. begin
  931. case FPosition of
  932. 0: begin
  933. case c of
  934. 'm': Inc(FPosition);
  935. 'p': begin
  936. FStack^.state := xsEscape_apos;
  937. Inc(FPosition);
  938. end;
  939. else
  940. goto err;
  941. end;
  942. end;
  943. 1: begin
  944. if c <> 'p' then goto err;
  945. Inc(FPosition);
  946. end;
  947. 2: begin
  948. if c <> ';' then goto err;
  949. FValue.Append(XML_AMP, 1);
  950. FStack^.state := FStack^.savedstate;
  951. end;
  952. end;
  953. end;
  954. xsEscape_apos:
  955. begin
  956. case FPosition of
  957. 0: begin
  958. case c of
  959. 'p': Inc(FPosition);
  960. 'm': begin
  961. FStack^.state := xsEscape_amp;
  962. Inc(FPosition);
  963. end;
  964. else
  965. goto err;
  966. end;
  967. end;
  968. 1: begin
  969. if c <> 'o' then goto err;
  970. Inc(FPosition);
  971. end;
  972. 2: begin
  973. if c <> 's' then goto err;
  974. Inc(FPosition);
  975. end;
  976. 3: begin
  977. if c <> ';' then goto err;
  978. FValue.Append(XML_SQU, 1);
  979. FStack^.state := FStack^.savedstate;
  980. end;
  981. end;
  982. end;
  983. xsEscape_quot:
  984. begin
  985. case FPosition of
  986. 0: begin
  987. if c <> 'u' then goto err;
  988. Inc(FPosition);
  989. end;
  990. 1: begin
  991. if c <> 'o' then goto err;
  992. Inc(FPosition);
  993. end;
  994. 2: begin
  995. if c <> 't' then goto err;
  996. Inc(FPosition);
  997. end;
  998. 3: begin
  999. if c <> ';' then goto err;
  1000. FValue.Append(XML_DQU, 1);
  1001. FStack^.state := FStack^.savedstate;
  1002. end;
  1003. end;
  1004. end;
  1005. xsEscape_char:
  1006. begin
  1007. if (SOIChar(c) >= 256) then goto err;
  1008. case AnsiChar(c) of
  1009. '0'..'9':
  1010. begin
  1011. FPosition := SOIChar(c) - 48;
  1012. FStack^.state := xsEscape_char_num;
  1013. end;
  1014. 'x':
  1015. begin
  1016. FStack^.state := xsEscape_char_hex;
  1017. end
  1018. else
  1019. goto err;
  1020. end;
  1021. end;
  1022. xsEscape_char_num:
  1023. begin
  1024. if (SOIChar(c) >= 256) then goto err;
  1025. case AnsiChar(c) of
  1026. '0'..'9':FPosition := (FPosition * 10) + (SOIChar(c) - 48);
  1027. ';': begin
  1028. FValue.Append(@FPosition, 1);
  1029. FStack^.state := FStack^.savedstate;
  1030. end;
  1031. else
  1032. goto err;
  1033. end;
  1034. end;
  1035. xsEscape_char_hex:
  1036. begin
  1037. if (c >= #256) then goto err;
  1038. if (AnsiChar(c) in hex) then
  1039. begin
  1040. FPosition := (FPosition * 16) + SOIChar(hexdigit(c));
  1041. end else
  1042. if c = ';' then
  1043. begin
  1044. FValue.Append(@FPosition, 1);
  1045. FStack^.state := FStack^.savedstate;
  1046. end else
  1047. goto err;
  1048. end;
  1049. xsEnd:
  1050. begin
  1051. if(FStack^.prev = nil) then Break;
  1052. if FStack^.obj <> nil then
  1053. begin
  1054. if FPack then
  1055. packend else
  1056. begin
  1057. anobject := FStack^.prev^.obj.AsObject[xmlchildren];
  1058. if anobject = nil then
  1059. begin
  1060. anobject := TSuperObject.Create(stArray);
  1061. FStack^.prev^.obj.AsObject[xmlchildren] := anobject;
  1062. end;
  1063. anobject.AsArray.Add(FStack^.obj);
  1064. end;
  1065. end;
  1066. StackDown;
  1067. goto redo;
  1068. end;
  1069. end;
  1070. inc(p);
  1071. inc(read);
  1072. until (c = #0);
  1073. if FStack^.state = xsEnd then
  1074. begin
  1075. if FPack then
  1076. packend;
  1077. FError := xeSuccess;
  1078. end else
  1079. FError := xeError;
  1080. Result := read;
  1081. exit;
  1082. err:
  1083. FError := xeError;
  1084. Result := read;
  1085. end;
  1086. function XMLParseFile(const FileName: string; pack: Boolean; onpi: TOnProcessingInstruction): ISuperObject;
  1087. var
  1088. stream: TFileStream;
  1089. begin
  1090. stream := TFileStream.Create(FileName, fmOpenRead, fmShareDenyWrite);
  1091. try
  1092. Result := XMLParseStream(stream, pack, onpi);
  1093. finally
  1094. stream.Free;
  1095. end;
  1096. end;
  1097. procedure TSuperXMLParser.StackDown;
  1098. var
  1099. prev: PSuperXMLStack;
  1100. begin
  1101. if FStack <> nil then
  1102. begin
  1103. prev := FStack^.prev;
  1104. FStack^.obj := nil;
  1105. FreeMem(FStack);
  1106. FStack := prev;
  1107. if FStack <> nil then
  1108. FStack^.next := nil;
  1109. end;
  1110. end;
  1111. procedure TSuperXMLParser.StackUp;
  1112. var
  1113. st: PSuperXMLStack;
  1114. begin
  1115. {$IFDEF FPC}
  1116. st := nil;
  1117. {$ENDIF}
  1118. GetMem(st, SizeOf(st^));
  1119. FillChar(st^, SizeOf(st^), 0);
  1120. st^.state := xsEatSpaces;
  1121. st^.savedstate := xsStart;
  1122. st^.prev := FStack;
  1123. if st^.prev <> nil then
  1124. st^.prev^.next := st;
  1125. st^.next := nil;
  1126. st^.obj := nil;
  1127. FStack := st;
  1128. end;
  1129. function utf8toucs2(src: PAnsiChar; srclen: Integer; dst: PWideChar; unused: PInteger): Integer;
  1130. var
  1131. ch: Byte;
  1132. ret: Word;
  1133. min: Cardinal;
  1134. rem, com: integer;
  1135. label
  1136. redo;
  1137. begin
  1138. Result := 0;
  1139. ret := 0;
  1140. rem := 0;
  1141. min := 0;
  1142. if unused <> nil then
  1143. unused^ := 0;
  1144. if(src = nil) or (srclen = 0) then
  1145. begin
  1146. dst^ := #0;
  1147. Exit;
  1148. end;
  1149. while srclen > 0 do
  1150. begin
  1151. ch := Byte(src^);
  1152. inc(src);
  1153. dec(srclen);
  1154. redo:
  1155. if (ch and $80) = 0 then
  1156. begin
  1157. dst^ := WideChar(ch);
  1158. inc(Result);
  1159. end else
  1160. begin
  1161. if((ch and $E0) = $C0) then
  1162. begin
  1163. min := $80;
  1164. rem := 1;
  1165. ret := ch and $1F;
  1166. end else
  1167. if((ch and $F0) = $E0) then
  1168. begin
  1169. min := $800;
  1170. rem := 2;
  1171. ret := ch and $0F;
  1172. end else
  1173. // too large utf8 bloc
  1174. // ignore and continue
  1175. continue;
  1176. com := rem;
  1177. while(rem <> 0) do
  1178. begin
  1179. dec(rem);
  1180. if(srclen = 0) then
  1181. begin
  1182. if unused <> nil then
  1183. unused^ := com;
  1184. Exit;
  1185. end;
  1186. ch := Byte(src^);
  1187. inc(src);
  1188. dec(srclen);
  1189. if((ch and $C0) = $80) then
  1190. begin
  1191. ret := ret shl 6;
  1192. ret := ret or (ch and $3F);
  1193. end else
  1194. begin
  1195. // unterminated utf8 bloc :/
  1196. // try next one
  1197. goto redo;
  1198. end;
  1199. end;
  1200. if (ret >= min) then
  1201. begin
  1202. dst^ := WideChar(ret);
  1203. inc(Result);
  1204. end else
  1205. // too small utf8 bloc
  1206. // ignore and continue
  1207. Continue;
  1208. end;
  1209. inc(dst);
  1210. end;
  1211. end;
  1212. function XMLParseStream(stream: TStream; pack: Boolean; onpi: TOnProcessingInstruction): ISuperObject;
  1213. const
  1214. CP_UTF8 = 65001;
  1215. var
  1216. wbuffer: array[0..1023] of SOChar;
  1217. abuffer: array[0..1023] of AnsiChar;
  1218. len, read, cursor: Integer;
  1219. PI, PIParent: ISuperObject;
  1220. bom: array[0..2] of byte;
  1221. encoding: TSuperXMLEncoding;
  1222. encodingstr: string;
  1223. cp: Integer;
  1224. ecp: ISuperObject;
  1225. function getbuffer: Integer;
  1226. var
  1227. size, unusued: Integer;
  1228. begin
  1229. case encoding of
  1230. {$IFNDEF UNIX}
  1231. xnANSI:
  1232. begin
  1233. size := stream.Read(abuffer, sizeof(abuffer));
  1234. result := MultiByteToWideChar(cp, 0, @abuffer, size, @wbuffer, sizeof(wbuffer));
  1235. end;
  1236. {$ENDIF}
  1237. xnUTF8:
  1238. begin
  1239. size := stream.Read(abuffer, sizeof(abuffer));
  1240. result := utf8toucs2(@abuffer, size, @wbuffer, @unusued);
  1241. if unusued > 0 then
  1242. stream.Seek(-unusued, soFromCurrent);
  1243. end;
  1244. xnUnicode: Result := stream.Read(wbuffer, sizeof(wbuffer)) div sizeof(SOChar);
  1245. else
  1246. Result := 0;
  1247. end;
  1248. end;
  1249. label
  1250. redo, retry;
  1251. begin
  1252. // init knowned code pages
  1253. ecp := so('{iso-8859-1: 28591,'+
  1254. 'iso-8859-2: 28592,'+
  1255. 'iso-8859-3: 28593,'+
  1256. 'iso-8859-4: 28594,'+
  1257. 'iso-8859-5: 28595,'+
  1258. 'iso-8859-6: 28596,'+
  1259. 'iso-8859-7: 28597,'+
  1260. 'iso-8859-8: 28598,'+
  1261. 'iso-8859-9: 28599,'+
  1262. 'iso 8859-15: 28605,'+
  1263. 'iso-2022-jp: 50220,'+
  1264. 'shift_jis: 932,'+
  1265. 'euc-jp: 20932,'+
  1266. 'ascii: 20127,'+
  1267. 'windows-1251: 1251,'+
  1268. 'windows-1252: 1252}');
  1269. // detect bom
  1270. stream.Seek(0, soFromBeginning);
  1271. len := stream.Read(bom, sizeof(bom));
  1272. if (len >= 2) and (bom[0] = $FF) and (bom[1] = $FE) then
  1273. begin
  1274. encoding := xnUnicode;
  1275. stream.Seek(2, soFromBeginning);
  1276. end else
  1277. if (len = 3) and (bom[0] = $EF) and (bom[1] = $BB) and (bom[2] = $BF) then
  1278. begin
  1279. encoding := xnUTF8;
  1280. cp := CP_UTF8;
  1281. end else
  1282. begin
  1283. encoding := xnUTF8;
  1284. cp := 0;
  1285. stream.Seek(0, soFromBeginning);
  1286. end;
  1287. with TSuperXMLParser.Create(pack) do
  1288. try
  1289. len := getbuffer;
  1290. while len > 0 do
  1291. begin
  1292. retry:
  1293. read := ParseBuffer(@wbuffer, PI, PIParent, len);
  1294. cursor := 0;
  1295. redo:
  1296. case FError of
  1297. xeContinue: len := getbuffer;
  1298. xeSuccess, xeError: Break;
  1299. xeProcessInst:
  1300. begin
  1301. if (PIParent = nil) and (PI.AsObject.S[xmlname] = 'xml') then
  1302. begin
  1303. if pack then
  1304. encodingstr := LowerCase(trim(PI.S['encoding'])) else
  1305. encodingstr := LowerCase(trim(PI.S[xmlattributes + '.encoding']));
  1306. if (encodingstr <> '') then
  1307. case encoding of
  1308. xnUTF8: if(cp = CP_UTF8) then
  1309. begin
  1310. if (encodingstr <> 'utf-8') then
  1311. begin
  1312. FError := xeError;
  1313. Break;
  1314. end;
  1315. end else
  1316. begin
  1317. cp := ecp.I[encodingstr];
  1318. if cp > 0 then
  1319. begin
  1320. {$IFNDEF UNIX}
  1321. encoding := xnANSI;
  1322. Reset;
  1323. stream.Seek(0, soFromBeginning);
  1324. len := getbuffer;
  1325. goto retry;
  1326. {$ELSE}
  1327. raise Exception.Create('charset not implemented');
  1328. {$ENDIF}
  1329. end;
  1330. end;
  1331. xnUnicode:
  1332. if (encodingstr <> 'utf-16') and (encodingstr <> 'unicode') then
  1333. begin
  1334. FError := xeError;
  1335. Break;
  1336. end;
  1337. end;
  1338. end else
  1339. if Assigned(onpi) then
  1340. onpi(PI, PIParent);
  1341. inc(cursor, read);
  1342. if cursor >= len then
  1343. begin
  1344. len := getbuffer;
  1345. continue;
  1346. end;
  1347. read := ParseBuffer(@wbuffer[cursor], PI, PIParent, len - cursor);
  1348. goto redo;
  1349. end;
  1350. end;
  1351. end;
  1352. if FError = xeSuccess then
  1353. Result := FStack^.obj else
  1354. Result := nil;
  1355. finally
  1356. Free;
  1357. end;
  1358. end;
  1359. function XMLParseString(const data: SOString; pack: Boolean; onpi: TOnProcessingInstruction): ISuperObject;
  1360. var
  1361. PI, PIParent: ISuperObject;
  1362. cursor, read: Integer;
  1363. label
  1364. redo;
  1365. begin
  1366. with TSuperXMLParser.Create(pack) do
  1367. try
  1368. cursor := 0;
  1369. read := ParseBuffer(PSOChar(data), PI, PIParent);
  1370. redo:
  1371. case FError of
  1372. xeSuccess: Result := FStack^.obj;
  1373. xeError: Result := nil;
  1374. xeProcessInst:
  1375. begin
  1376. if Assigned(onpi) then
  1377. onpi(PI, PIParent);
  1378. inc(cursor, read);
  1379. read := ParseBuffer(@data[cursor+1], PI, PIParent);
  1380. goto redo;
  1381. end;
  1382. end;
  1383. finally
  1384. Free;
  1385. end;
  1386. end;
  1387. end.