PageRenderTime 62ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/interfaces/xml2json/xml2json.js

https://github.com/floviolleau/exchangecalendar
JavaScript | 953 lines | 871 code | 58 blank | 24 comment | 172 complexity | 574a027c987b3afa32d6303dd553ee9c MD5 | raw file
  1. var Cc = Components.classes;
  2. var Ci = Components.interfaces;
  3. var Cu = Components.utils;
  4. var Cr = Components.results;
  5. var components = Components;
  6. function STACK(aDepth, aSkip) {
  7. let depth = aDepth || 10;
  8. let skip = aSkip || 0;
  9. let stack = "";
  10. let frame = components.stack.caller;
  11. for (let i = 1; i <= depth + skip && frame; i++) {
  12. if (i > skip) {
  13. stack += i + ": [" + frame.filename + ":" +
  14. frame.lineNumber + "] " + frame.name + "\n";
  15. }
  16. frame = frame.caller;
  17. }
  18. return stack;
  19. }
  20. function typeString(o) {
  21. if (typeof o != 'object')
  22. return typeof o;
  23. if (o === null)
  24. return "null";
  25. //object, array, function, date, regexp, string, number, boolean, error
  26. var internalClass = Object.prototype.toString.call(o)
  27. .match(/\[object\s(\w+)\]/)[1];
  28. return internalClass.toLowerCase();
  29. }
  30. function isObject(obj) {
  31. return (typeString(obj) == "object");
  32. }
  33. function isArray(obj) {
  34. return (typeString(obj) == "array");
  35. }
  36. function isInList(inArray, inStr)
  37. {
  38. return (inArray[inStr] !== undefined);
  39. }
  40. const specialChars1 = { " ": true,
  41. "\n" : true,
  42. "\r" : true,
  43. "\t" : true };
  44. function findCharacter(aXMLString, aSP, aChar)
  45. {
  46. if (!aXMLString) return -1;
  47. var pos = aSP;
  48. var strLength = aXMLString.length;
  49. // while ((pos < strLength) && (aXMLString[pos] != aChar)) {
  50. while ((pos < strLength) && (aXMLString.charAt(pos) != aChar)) {
  51. pos++;
  52. }
  53. if (pos < strLength) {
  54. return pos;
  55. }
  56. return -1;
  57. }
  58. function findString(aXMLString, aSP, aNeedle)
  59. {
  60. if (!aXMLString) return -1;
  61. var pos = aSP;
  62. var needleLength = aNeedle.length;
  63. var strLength = aXMLString.length - needleLength + 1;
  64. while ((pos < strLength) && (aXMLString.substr(pos, needleLength) != aNeedle)) {
  65. pos++;
  66. }
  67. if (pos < strLength) {
  68. return pos;
  69. }
  70. return -1;
  71. }
  72. function splitOnCharacter(aXMLString, aSP, aSplitCharacter)
  73. {
  74. if (!aXMLString) {
  75. return null;
  76. }
  77. var tmpPos = aSP;
  78. var result = "";
  79. var notClosed = true;
  80. var notQuoteOpen = true;
  81. var quotesUsed = "";
  82. var strLen = aXMLString.length;
  83. var splitCharIsArray = isArray(aSplitCharacter);
  84. while ((tmpPos < strLen) && (notClosed)) {
  85. // if ((aXMLString[tmpPos] == "'") || (aXMLString[tmpPos] == '"')) {
  86. if ((aXMLString.charAt(tmpPos) == "'") || (aXMLString.charAt(tmpPos) == '"')) {
  87. // We found quotes. Do they belong to our string.
  88. if (notQuoteOpen) {
  89. quotesUsed = aXMLString.charAt(tmpPos);
  90. notQuoteOpen = false;
  91. }
  92. else {
  93. // if (aXMLString[tmpPos] == quotesUsed) {
  94. if (aXMLString.charAt(tmpPos) == quotesUsed) {
  95. quotesUsed = "";
  96. notQuoteOpen = true;
  97. }
  98. }
  99. }
  100. var hitSplitCharacter = false;
  101. if (notQuoteOpen) {
  102. if (splitCharIsArray) {
  103. for (var index in aSplitCharacter) {
  104. if (aXMLString.substr(tmpPos,aSplitCharacter[index].length) == aSplitCharacter[index]) {
  105. hitSplitCharacter = true;
  106. break;
  107. }
  108. }
  109. }
  110. else {
  111. if (aXMLString.substr(tmpPos,aSplitCharacter.length) == aSplitCharacter) {
  112. hitSplitCharacter = true;
  113. }
  114. }
  115. }
  116. if (hitSplitCharacter) {
  117. notClosed = false;
  118. }
  119. else {
  120. // result += aXMLString[tmpPos];
  121. result += aXMLString.charAt(tmpPos);
  122. }
  123. tmpPos++;
  124. }
  125. if (!notClosed) {
  126. return result;
  127. }
  128. else {
  129. return null;
  130. }
  131. }
  132. var replaceFromXML = function _replaceFromXML(str, r1)
  133. {
  134. var result = str;
  135. if (r1[0] == "#") {
  136. if (r1[1] == "x") {
  137. // hexadecimal
  138. result = String.fromCharCode(parseInt(r1.substr(2),16))
  139. }
  140. else {
  141. // Decimal
  142. result = String.fromCharCode(parseInt(r1.substr(1),10))
  143. }
  144. }
  145. else {
  146. switch (r1) {
  147. case "amp": result = "&"; break;
  148. case "quot": result = '"'; break;
  149. case "apos": result = "'"; break;
  150. case "lt": result = "<"; break;
  151. case "gt": result = ">"; break;
  152. }
  153. }
  154. return result;
  155. }
  156. function convertSpecialCharatersFromXML(aXMLString)
  157. {
  158. if (!aXMLString) return aXMLString;
  159. var result = aXMLString;
  160. // Convert special characters
  161. result = result.replace(/&(quot|apos|lt|gt|amp|#x[0123456789ancdefABCDEF][0123456789ancdefABCDEF]?[0123456789ancdefABCDEF]?[0123456789ancdefABCDEF]?|#[0123456789][0123456789]?[0123456789]?[0123456789]?);/g, replaceFromXML);
  162. return result;
  163. }
  164. var replaceToXML = function _replaceToXML(str, r1)
  165. {
  166. var result = str;
  167. switch (r1) {
  168. case "&": result = "&amp;"; break;
  169. case '"': result = "&quot;"; break;
  170. case "'": result = "&apos;"; break;
  171. case "<": result = "&lt;"; break;
  172. case ">": result = "&gt;"; break;
  173. }
  174. return result;
  175. }
  176. function convertSpecialCharatersToXML(aXMLString)
  177. {
  178. if ((aXMLString === null) || (aXMLString === undefined)) return aXMLString;
  179. var result = aXMLString.toString();
  180. // Convert special characters
  181. result = result.replace(/(&|\x22|\x27|<|>)/g, replaceToXML);
  182. return result;
  183. }
  184. function trim(aValue)
  185. {
  186. var strLength = aValue.length;
  187. var leftPos = 0;
  188. while ((leftPos < strLength) && (aValue.charAt(leftPos) == " ")) {
  189. leftPos++;
  190. }
  191. var rightPos = strLength-1;
  192. while ((rightPos >= 0) && (aValue.charAt(rightPos) == " ")) {
  193. rightPos--;
  194. }
  195. return aValue.substr(leftPos, rightPos - leftPos + 1);
  196. }
  197. function hasXMLHeader(aStr, aSP)
  198. {
  199. if (!aStr) return 0;
  200. var pos = findCharacter(aStr, aSP, "<");
  201. var strLength = aStr.length;
  202. if (pos > -1) {
  203. pos++;
  204. var tc = aStr.charAt(pos);
  205. if ( (pos < strLength) && (tc == "?")) {
  206. pos++;
  207. if (aStr.substr(pos, 4) == "xml ") {
  208. var tmpPos = findString(aStr, pos, "?>");
  209. if (tmpPos == -1) {throw -20;} // Error invalid special tag
  210. else {
  211. return (tmpPos+2);
  212. }
  213. }
  214. else {throw -21;} //ERR_MISSING_SPECIAL_TAG
  215. }
  216. }
  217. return 0;
  218. }
  219. function splitTagName(aTagName) {
  220. var ns = null;
  221. var tn = null;
  222. var sepPos = aTagName.indexOf(tsep);
  223. if (sepPos > -1) {
  224. ns = aTagName.substr(0,sepPos);
  225. tn = aTagName.substr(sepPos+1);
  226. }
  227. else {
  228. tn = aTagName;
  229. }
  230. return { tagName: tn, nameSpace: ns };
  231. }
  232. function convertComparisonPart(a, aJSONObject){
  233. var r = [];
  234. var tc = a[0];
  235. if ((tc == "/") || (tc == ".") || (tc == "@")) {
  236. r = realXPath(aJSONObject, a);
  237. }
  238. else {
  239. r = [];
  240. if ( (tc == "'") || (tc == '"')) {
  241. r.push(a.substr(1,a.length-2));
  242. }
  243. else {
  244. if (isNaN(a)) {
  245. r = realXPath(aJSONObject, a);
  246. }
  247. else {
  248. r.push(Number(a));
  249. }
  250. }
  251. }
  252. return r;
  253. }
  254. function ifFunction(aCondition, aJSONObject){
  255. var level = 0;
  256. var tmpCondition = trim(aCondition);
  257. var compareList = [];
  258. while (tmpCondition != "") {
  259. var startPos = 0;
  260. var weHaveSubCondition = false;
  261. if (tmpCondition[0] == "(") {
  262. var subCondition = splitOnCharacter(tmpCondition.substr(1), 0, ")");
  263. if (subCondition) {
  264. startPos = subCondition.length;
  265. weHaveSubCondition = true;
  266. }
  267. else {
  268. throw "XPath error: Did not find closing round bracket '"+aJSONObject.tagName+"' for condition:"+aCondition;
  269. }
  270. }
  271. var splitPart = splitOnCharacter(tmpCondition.toLowerCase(), startPos, [" and ", " or "]);
  272. var operator = null;
  273. var comparison = null;
  274. if (splitPart) {
  275. splitPart = tmpCondition.substr(0, splitPart.length);
  276. tmpCondition = tmpCondition.substr(splitPart.length + 1);
  277. if (tmpCondition[0] == "a") {
  278. operator = "and";
  279. tmpCondition = tmpCondition.substr(4);
  280. }
  281. else {
  282. operator = "or";
  283. tmpCondition = tmpCondition.substr(3);
  284. }
  285. }
  286. else {
  287. splitPart = tmpCondition;
  288. tmpCondition = "";
  289. }
  290. if (weHaveSubCondition) {
  291. compareList.push( { left: subCondition, right: "", operator: operator, comparison: comparison, subCondition: subCondition} );
  292. }
  293. else {
  294. var splitPart2 = splitOnCharacter(splitPart, 0, ["!=", "<=", ">=", "<", "=", ">"]);
  295. if (splitPart2) {
  296. // Get comparison type
  297. var smallerThen = false;
  298. var equalTo = false;
  299. var biggerThen = false;
  300. var splitPos2 = splitPart2.length;
  301. switch (splitPart.charAt(splitPos2)) {
  302. case "!":comparison = "!=";break;
  303. case "<":comparison = "<";if (splitPart.charAt(splitPos2+1) == "=") comparison = "<=";break;
  304. case "=":comparison = "=";break;
  305. case ">":comparison = ">";if (splitPart.charAt(splitPos2+1) == "=") comparison = ">=";break;
  306. }
  307. compareList.push( { left: trim(splitPart2), right: trim(splitPart.substr(splitPart2.length+comparison.length)), operator: operator, comparison: comparison, subCondition: subCondition} );
  308. }
  309. else {
  310. compareList.push( { left: trim(splitPart), right: "", operator: operator, comparison: comparison, subCondition: subCondition} );
  311. }
  312. }
  313. }
  314. var totalResult = true;
  315. var lastOperator = null;
  316. for (let index in compareList) {
  317. var tmpResult = false;
  318. if (compareList[index].subCondition) {tmpResult = ifFunction(compareList[index].left, aJSONObject);}
  319. else {
  320. let tmpLeft = convertComparisonPart(compareList[index].left, aJSONObject);
  321. let tmpRight = convertComparisonPart(compareList[index].right, aJSONObject);
  322. if (tmpLeft.length > 0) {
  323. if (compareList[index].comparison) {
  324. // Filter out ony the valid ones.
  325. if (tmpRight.length > 0) {
  326. var x = 0;
  327. tmpResult = false;
  328. while ((x < tmpLeft.length) && (!tmpResult)) {
  329. if ((typeof tmpLeft[x] === "string") || (tmpLeft[x] instanceof String) || (typeof tmpLeft[x] === "number")) {
  330. var evalConditionLeft = tmpLeft[x].toString();
  331. }
  332. else {
  333. var evalConditionLeft = realGetValue(tmpLeft[x]).toString();
  334. }
  335. var y = 0;
  336. while ((y < tmpRight.length) && (!tmpResult)) {
  337. if ((typeof tmpRight[y] === "string") || (tmpRight[y] instanceof String) || (typeof tmpRight[y] === "number")) {
  338. var evalConditionRight = tmpRight[y].toString();
  339. }
  340. else {var evalConditionRight = realGetValue(tmpRight[y]).toString();}
  341. switch (compareList[index].comparison) {
  342. case "!=":tmpResult = (evalConditionLeft != evalConditionRight);break;
  343. case "<=":tmpResult = (evalConditionLeft <= evalConditionRight);break;
  344. case ">=":tmpResult = (evalConditionLeft >= evalConditionRight);break;
  345. case "<":tmpResult = (evalConditionLeft < evalConditionRight);break;
  346. case "=":tmpResult = (evalConditionLeft==evalConditionRight);break;
  347. case ">":tmpResult = (evalConditionLeft > evalConditionRight);break;
  348. }
  349. y++;
  350. }
  351. x++;
  352. }
  353. }
  354. }
  355. else {
  356. tmpResult = true;
  357. }
  358. }
  359. else {tmpResult = false;}
  360. tmpLeft = null;
  361. tmpRight = null;
  362. }
  363. switch (lastOperator) {
  364. case "and":totalResult = (totalResult && tmpResult);break;
  365. case "or":totalResult = (totalResult || tmpResult);break;
  366. case null:totalResult = tmpResult;break;
  367. }
  368. if (compareList[index].operator) {
  369. if ((compareList[index].operator == "and") && (!totalResult)) {return false;}
  370. if ((compareList[index].operator == "or") && (totalResult)) {return true;}
  371. }
  372. lastOperator = compareList[index].operator;
  373. }
  374. return totalResult;
  375. }
  376. function realGetValue(aParent) {
  377. if (!aParent) throw -60;
  378. if (!aParent[tcontent]) return "";
  379. let result = "";
  380. let i = 0;
  381. while (i < aParent[tcontent].length) {
  382. result = result + aParent[tcontent][i];
  383. i++;
  384. }
  385. return convertSpecialCharatersFromXML(result);
  386. }
  387. function realGetTags(aParent, aTagName) {
  388. if ((!aParent) || (!aParent[telements])) throw -54;
  389. let result = [];
  390. var tmpTN = splitTagName(aTagName);
  391. var i = 0;
  392. while (i < aParent[telements].length) {
  393. // if ((aParent[telements][i][tnamespace] == tmpTN.nameSpace) && (aParent[telements][i].tagName == tmpTN.tagName)) {
  394. if (aParent[telements][i].tagName == tmpTN.tagName) { // We ignore the namespace for now.
  395. result.push(aParent[telements][i]);
  396. }
  397. i++;
  398. }
  399. return result;
  400. }
  401. function realXPath(aParent, aPath){
  402. //dump("XPath:"+aPath+"("+STACK(6)+")\n");
  403. //dump("aParent:"+JSON.stringify(aParent)+"\n");
  404. //dump("..\n");
  405. var tmpPath = aPath;
  406. var result = [];
  407. if (tmpPath[0] == "/") {
  408. tmpPath = tmpPath.substr(1);
  409. }
  410. switch (tmpPath[0]) {
  411. case "@" : // Find attribute within this element
  412. let attrName = tmpPath.substr(1);
  413. if ((aParent[tattributes]) && (aParent[tattributes][attrName])) {
  414. //dump("XPath:found attribute. value="+String(aParent[tattributes][attrName])+"\n");
  415. result.push(String(aParent[tattributes][attrName]));
  416. }
  417. //dump("XPath find attribute '"+attrName+"'. result.length='"+result.length+"'\n");
  418. tmpPath = "";
  419. break;
  420. case "*" : // Wildcard. Will parse all children.
  421. tmpPath = tmpPath.substr(1);
  422. let i = 0;
  423. while (i < aParent[telements].length) {
  424. result.push(aParent[telements][i]);
  425. i++;
  426. }
  427. break;
  428. case "[" : // Compare/match function
  429. let index = splitOnCharacter(tmpPath.substr(1), 0, "]");
  430. if (!index) {throw "XPath error: Did not find closing square bracket. tagName:"+aParent.tagName+", tmpPath:"+tmpPath;}
  431. tmpPath = tmpPath.substr(index.length+2);
  432. index = trim(index);
  433. if (index != "") {
  434. if (ifFunction(index, aParent)) {
  435. result.push(aParent);
  436. }
  437. else {
  438. return result;
  439. }
  440. }
  441. else {
  442. throw "XPath compare error:No Value between square brackets:"+aParent.tagName+"["+index+"]";
  443. }
  444. break;
  445. default:
  446. let bracketPos = tmpPath.indexOf("[");
  447. let forwardSlashPos = tmpPath.indexOf("/");
  448. let splitPos = tmpPath.length;
  449. if ((bracketPos < splitPos) && (bracketPos > -1)) {splitPos = bracketPos;}
  450. if ((forwardSlashPos < splitPos) && (forwardSlashPos > -1)) {splitPos = forwardSlashPos;}
  451. let tmpPath2 = tmpPath.substr(0, splitPos);
  452. tmpPath = tmpPath.substr(splitPos);
  453. let equalTags = [];
  454. equalTags = realGetTags(aParent,tmpPath2);
  455. result = equalTags;
  456. }
  457. if ((result.length > 0) && (tmpPath != "")) {
  458. let finalResult = [];
  459. let i = 0;
  460. while (i < result.length) {
  461. var tmpResult = realXPath(result[i], tmpPath);
  462. if (!isArray(tmpResult)) { // Check if answer is an Array or a String. String is returned on attribute search.
  463. finalResult = tmpResult;
  464. }
  465. else {
  466. let j = 0;
  467. while (j < tmpResult.length) {
  468. finalResult.push(tmpResult[j]);
  469. j++;
  470. }
  471. }
  472. i++;
  473. }
  474. result = finalResult;
  475. }
  476. return result;
  477. }
  478. function realElementToString(aElement) {
  479. if (!aElement.tagName) return "";
  480. //dump(" @@@@@:"+JSON.stringify(aElement)+"\n");
  481. let result = "<";
  482. if (aElement[tnamespace]) result = result + aElement[tnamespace] + tsep;
  483. result = result + aElement.tagName;
  484. if (aElement[tattributes]) {
  485. for (var attrName in aElement[tattributes]) {
  486. result = result + " " + attrName + "="+'"' + aElement[tattributes][attrName]+'"';
  487. }
  488. }
  489. if ((aElement[tcontent]) || (aElement[telements].length > 0)) {
  490. result = result + ">";
  491. if ((aElement[tcontent]) && (aElement[tcontent].length > 0)) {
  492. let i = 0;
  493. while (i < aElement[tcontent].length) {
  494. result = result + aElement[tcontent][i];
  495. i++;
  496. }
  497. }
  498. let i = 0;
  499. while (i < aElement[telements].length) {
  500. result = result + realElementToString(aElement[telements][i]);
  501. i++;
  502. }
  503. result = result + "</";
  504. if (aElement[tnamespace]) result = result + aElement[tnamespace] + tsep;
  505. result = result + aElement.tagName + ">";
  506. }
  507. else {
  508. result = result + "/>";
  509. }
  510. return result;
  511. }
  512. function realSetAttribute(aParent, aName, aValue) {
  513. if ((!aParent) || (!aParent[telements])) throw -51;
  514. if (!aParent[tattributes]) {
  515. aParent[tattributes] = {};
  516. }
  517. aParent[tattributes][aName] = aValue;
  518. }
  519. function realAddContent(aParent, aString) {
  520. //dump("addContent: aString="+aString+"\n");
  521. if ((!aParent) || (!aParent[telements])) throw -55;
  522. if (!aParent[tcontent]) {
  523. aParent[tcontent] = [];
  524. }
  525. aParent[tcontent].push(aString);
  526. }
  527. function realClosingTag(aParent, aTagName) {
  528. //dump("closingTag: aTagName="+aTagName+"\n");
  529. var tmpTN = splitTagName(aTagName);
  530. let closingMatchesOpening = false;
  531. if (tmpTN.tagName == aParent.tagName) {
  532. if (tmpTN.nameSpace == aParent[tnamespace]) {
  533. closingMatchesOpening = true;
  534. }
  535. }
  536. if (!closingMatchesOpening) {
  537. throw -5; // Closing element does not match opening element.
  538. }
  539. else {
  540. if (aParent.parent) {
  541. let result = aParent.parent;
  542. aParent.parent = null;
  543. delete aParent['parent'];
  544. return result;
  545. }
  546. else {
  547. throw -6; // We should never get here. But in case we do. Wee see a closing element for which no opening element was seen.
  548. }
  549. }
  550. }
  551. function realOpeningTag(aParent, aTagName) {
  552. //dump("openingTag: aTagName="+aTagName+"\n");
  553. var tmpTN = splitTagName(aTagName);
  554. let tmpElement = { parent: aParent,
  555. e: [],
  556. n: tmpTN.nameSpace,
  557. tagName: tmpTN.tagName};
  558. aParent[telements].push(tmpElement);
  559. return tmpElement;
  560. }
  561. function realSetAttributeStr(aParent, aString) {
  562. //dump("setAttributeStr 1: aString="+aString+"\n");
  563. aString = aString.replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "");
  564. var sp = aString.indexOf("=");
  565. if (sp == -1) {
  566. throw -13; // Equal sign not found.
  567. }
  568. var an = trim(aString.substr(0, sp));
  569. var av = trim(aString.substr(sp+1));
  570. var tc = av[0];
  571. if ((tc == "'") || (tc == '"')) {
  572. let vl = av.length;
  573. if (tc == av.charAt(vl-1)) {
  574. av = av.substr(1, vl-2);
  575. }
  576. else {
  577. throw -14; // Did not find closing quote
  578. }
  579. }
  580. //dump("setAttributeStr 2: name="+an+", value="+av+"\n");
  581. realSetAttribute(aParent, an, av);
  582. }
  583. var EXPORTED_SYMBOLS = ["xml2json", "telements", "tattributes", "tcontent", "convertSpecialCharatersFromXML", "convertSpecialCharatersToXML"];
  584. const tsep = ":";
  585. const telements = "e";
  586. const tattributes = "a";
  587. const tcontent = "c";
  588. const tnamespace = "n";
  589. var xml2json = {
  590. newJSON: function _newJSON() {
  591. return { e: [] };
  592. },
  593. addTagObject: function _addTagObject(aParent, aChildObject) {
  594. if ((!aParent) || (!aParent[telements])) throw -52;
  595. aParent[telements].push(aChildObject);
  596. return aParent[telements][aParent[telements].length-1];
  597. },
  598. getTags: function _getTags(aParent, aTagName) {
  599. return this.clone(realGetTags(aParent, aTagName));
  600. },
  601. getValue: function _getValue(aParent) {
  602. return realGetValue(aParent);
  603. },
  604. getTagValue: function _getTagValue(aParent, aTagName, aDefault) {
  605. if ((!aParent) || (!aParent[telements]) || (!aTagName)) throw "-62 aParent:"+aParent+", aTagName="+aTagName;
  606. let result = null;
  607. let i = 0;
  608. var tmpTN = splitTagName(aTagName);
  609. while ((!result) && (i < aParent[telements].length)) {
  610. if (aParent[telements][i].tagName == tmpTN.tagName) { // We ignore the namespace for now.
  611. result = realGetValue(aParent[telements][i]);
  612. }
  613. i++;
  614. }
  615. if (!result) result = aDefault;
  616. return result;
  617. },
  618. clone: function _clone(aElement) {
  619. return JSON.parse(JSON.stringify(aElement));
  620. },
  621. getTag: function _getTag(aParent, aTagName) {
  622. let result = null;
  623. var tmpTN = splitTagName(aTagName);
  624. var i = 0;
  625. while ((!result) && (i < aParent[telements].length)) {
  626. // if ((aParent[telements][i][tnamespace] == tmpTN.nameSpace) && (aParent[telements][i].tagName == tmpTN.tagName)) {
  627. if (aParent[telements][i].tagName == tmpTN.tagName) { // Namespace is ignored for now.
  628. return this.clone(aParent[telements][i]);
  629. }
  630. i++;
  631. }
  632. return null;
  633. },
  634. addTag: function _addTag(aParent, aTagName, aNameSpace, aValue) {
  635. if ((!aParent) || (!aParent[telements])) throw -53;
  636. var tmpJson = {tagName: aTagName,
  637. n: aNameSpace,
  638. e: []};
  639. if (aValue) {
  640. realAddContent(tmpJson, convertSpecialCharatersToXML(aValue));
  641. }
  642. aParent[telements].push(tmpJson);
  643. return aParent[telements][aParent[telements].length-1];
  644. },
  645. elementToString: function _elementToString(aElement) {
  646. return realElementToString(aElement);
  647. },
  648. toString: function _toString(aParent) {
  649. var result = "";
  650. var i = 0;
  651. //dump(" !!!!!:"+JSON.stringify(aParent)+"\n");
  652. if (aParent["tagName"]) {
  653. result = result + realElementToString(aParent);
  654. }
  655. else {
  656. while (i < aParent[telements].length) {
  657. result = result + realElementToString(aParent[telements][i]);
  658. i++;
  659. }
  660. }
  661. return result;
  662. },
  663. openingTag: function _openingTag(aParent, aTagName) {
  664. return realOpeningTag(aParent, aTagName);
  665. },
  666. addContent: function _addContent(aParent, aString) {
  667. realAddContent(aParent, aString);
  668. },
  669. closingTag: function _closingTag(aParent, aTagName) {
  670. return realClosingTag(aParent, aTagName);
  671. },
  672. getAttributeByTag: function _getAttributeByTag(aParent, aTagName, aName) {
  673. //dump("getAttributeByTag 1: aParent:"+aParent+", aTagName="+aTagName+", aName="+aName+"\n");
  674. if ((!aParent) || (!aParent[telements]) || (!aTagName)) throw -80;
  675. let i = 0;
  676. var tmpTN = splitTagName(aTagName);
  677. while (i < aParent[telements].length) {
  678. if ((tmpTN.tagName == aParent[telements][i].tagName) && (aParent[telements][i][tattributes])) { // We ignore namespace for now.
  679. if (aParent[telements][i][tattributes][aName]) {
  680. return aParent[telements][i][tattributes][aName];
  681. }
  682. }
  683. i++;
  684. }
  685. return null;
  686. },
  687. getAttribute: function _getAttribute(aParent, aName, aDefault) {
  688. if (!aParent) throw -70;
  689. if ((!aParent[tattributes]) || (!aParent[tattributes][aName])) {
  690. if (aDefault) {
  691. return aDefault;
  692. }
  693. return null;
  694. }
  695. return convertSpecialCharatersFromXML(aParent[tattributes][aName]);
  696. },
  697. setAttribute: function _setAttribute(aParent, aName, aValue) {
  698. realSetAttribute(aParent, aName, convertSpecialCharatersToXML(aValue));
  699. },
  700. setAttributeStr: function _setAttributeStr(aParent, aString) {
  701. realSetAttributeStr(aParent, aString);
  702. },
  703. parseXML: function _parseXML(aJSONObject, aXMLString) {
  704. var currentjson = aJSONObject;
  705. if (!aXMLString) return;
  706. try{
  707. var pos = 0;
  708. var xmlHeaderPos = hasXMLHeader(aXMLString, pos);
  709. if (xmlHeaderPos > 0) {
  710. //dump("We have an XML header. Going to strip it.\n");
  711. pos = xmlHeaderPos;
  712. }
  713. var strLength = aXMLString.length;
  714. while (pos < strLength) {
  715. var tmpPos = findCharacter(aXMLString, pos, "<");
  716. if (tmpPos > -1) {
  717. // Found openingcharacter of element.
  718. let skipped = tmpPos - pos;
  719. if (skipped > 0) {
  720. // Found data before element.
  721. realAddContent(currentjson,aXMLString.substr(pos, skipped));
  722. }
  723. pos = tmpPos + 1;
  724. }
  725. //var tc = aXMLString[pos];
  726. var tc = aXMLString.charAt(pos);
  727. if ( (pos < strLength) && (tc == "/")) {
  728. // Found character for closing element
  729. pos++;
  730. tmpPos = findCharacter(aXMLString, pos, ">");
  731. if (tmpPos > -1) {
  732. // found end character of closing element.
  733. currentjson = realClosingTag(currentjson, aXMLString.substr(pos, tmpPos-pos));
  734. }
  735. else {
  736. // Did not find end character of closing element. Error.
  737. throw -7;
  738. }
  739. pos = tmpPos + 1;
  740. }
  741. else {
  742. // Check element name
  743. if (pos < strLength) {
  744. let tmpPos = findCharacter(aXMLString, pos, ">");
  745. if (tmpPos > -1) {
  746. let elementName = "";
  747. //tc = aXMLString[pos];
  748. tc = aXMLString.charAt(pos);
  749. while ((pos < strLength) && (tc != ">") &&
  750. (tc != "/") && (!(isInList(specialChars1,tc)))) {
  751. elementName = elementName + tc;
  752. pos++;
  753. //tc = aXMLString[pos];
  754. tc = aXMLString.charAt(pos);
  755. }
  756. currentjson = realOpeningTag(currentjson, elementName);
  757. // We have an element name. Let see if it contains data or is closed.
  758. if ((pos < strLength) && (tc == "/")) {
  759. // It is closed.
  760. currentjson = realClosingTag(currentjson, elementName);
  761. pos++; pos++;
  762. }
  763. else {
  764. // Element is not closed. Let see if it contains attributes.
  765. if ((pos < strLength) && (isInList(specialChars1,tc))) {
  766. var attribute = "";
  767. pos++;
  768. //tc = aXMLString[pos];
  769. tc = aXMLString.charAt(pos);
  770. var quoteOpen = false;
  771. var seenAttributeSeparator = false;
  772. var quoteChar = "";
  773. while ((pos < strLength) &&
  774. (((tc != ">") && (tc != "/")) || (quoteOpen)) ) {
  775. attribute = attribute + tc;
  776. if ((!seenAttributeSeparator) && (tc == "=") && (!quoteOpen)){seenAttributeSeparator = true;}
  777. else {
  778. if (seenAttributeSeparator) {
  779. if ((tc == '"') || (tc == "'")) {
  780. if ((!quoteOpen) || ((quoteOpen) && (quoteChar == tc))) {
  781. quoteOpen = !quoteOpen;
  782. if (quoteOpen) {quoteChar = tc;}
  783. }
  784. }
  785. }
  786. }
  787. pos++;
  788. //tc = aXMLString[pos];
  789. tc = aXMLString.charAt(pos);
  790. if ((seenAttributeSeparator) && (pos < strLength) && (isInList(specialChars1,tc)) && (!quoteOpen)) {
  791. realSetAttributeStr(currentjson, attribute);
  792. attribute = "";
  793. seenAttributeSeparator = false;
  794. pos++;
  795. //tc = aXMLString[pos];
  796. tc = aXMLString.charAt(pos);
  797. }
  798. }
  799. if ((seenAttributeSeparator) && (!quoteOpen) && (pos < strLength) && (attribute.length > 0)) {
  800. realSetAttributeStr(currentjson, attribute);
  801. seenAttributeSeparator = false;
  802. attribute = "";
  803. }
  804. if ((pos < strLength) && (tc == "/")) {
  805. // Found opening tag with attributes which is also closed.
  806. currentjson = realClosingTag(currentjson, elementName);
  807. pos++;
  808. //tc = aXMLString[pos];
  809. tc = aXMLString.charAt(pos);
  810. }
  811. if (!((pos < strLength) && (tc == ">"))) {
  812. throw -8; // Expected closing character of element field
  813. }
  814. pos++;
  815. }
  816. else {
  817. if (!((pos < strLength) && (tc == ">"))) {
  818. throw -9; // Expected closing character of element field
  819. }
  820. pos++;
  821. }
  822. }
  823. }
  824. else {
  825. throw -10; // Expected closing character of element field but did not find it.
  826. }
  827. }
  828. else {
  829. throw -11; // No more characters left
  830. }
  831. }
  832. } // While.
  833. }
  834. catch(err){ dump(" !! Err:"+err+"("+STACK()+"\n");}
  835. },
  836. XPath: function _XPath(aParent, aPath){
  837. //dump("XPath:"+aPath+"\n");
  838. //dump("aParent:"+JSON.stringify(aParent)+"\n");
  839. //dump("..\n");
  840. return this.clone(realXPath(aParent, aPath));
  841. },
  842. }