Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

parse.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /**
  2. * Module dependencies.
  3. */
  4. var DOMParser = require('xmldom').DOMParser;
  5. /**
  6. * Module exports.
  7. */
  8. exports.parse = parse;
  9. var TEXT_NODE = 3;
  10. var CDATA_NODE = 4;
  11. var COMMENT_NODE = 8;
  12. /**
  13. * We ignore raw text (usually whitespace), <!-- xml comments -->,
  14. * and raw CDATA nodes.
  15. *
  16. * @param {Element} node
  17. * @returns {Boolean}
  18. * @api private
  19. */
  20. function shouldIgnoreNode (node) {
  21. return node.nodeType === TEXT_NODE
  22. || node.nodeType === COMMENT_NODE
  23. || node.nodeType === CDATA_NODE;
  24. }
  25. /**
  26. * Check if the node is empty. Some plist file has such node:
  27. * <key />
  28. * this node shoud be ignored.
  29. *
  30. * @see https://github.com/TooTallNate/plist.js/issues/66
  31. * @param {Element} node
  32. * @returns {Boolean}
  33. * @api private
  34. */
  35. function isEmptyNode(node){
  36. if(!node.childNodes || node.childNodes.length === 0) {
  37. return true;
  38. } else {
  39. return false;
  40. }
  41. }
  42. function invariant(test, message) {
  43. if (!test) {
  44. throw new Error(message);
  45. }
  46. }
  47. /**
  48. * Parses a Plist XML string. Returns an Object.
  49. *
  50. * @param {String} xml - the XML String to decode
  51. * @returns {Mixed} the decoded value from the Plist XML
  52. * @api public
  53. */
  54. function parse (xml) {
  55. var doc = new DOMParser().parseFromString(xml);
  56. invariant(
  57. doc.documentElement.nodeName === 'plist',
  58. 'malformed document. First element should be <plist>'
  59. );
  60. var plist = parsePlistXML(doc.documentElement);
  61. // the root <plist> node gets interpreted as an Array,
  62. // so pull out the inner data first
  63. if (plist.length == 1) plist = plist[0];
  64. return plist;
  65. }
  66. /**
  67. * Convert an XML based plist document into a JSON representation.
  68. *
  69. * @param {Object} xml_node - current XML node in the plist
  70. * @returns {Mixed} built up JSON object
  71. * @api private
  72. */
  73. function parsePlistXML (node) {
  74. var i, new_obj, key, val, new_arr, res, counter, type;
  75. if (!node)
  76. return null;
  77. if (node.nodeName === 'plist') {
  78. new_arr = [];
  79. if (isEmptyNode(node)) {
  80. return new_arr;
  81. }
  82. for (i=0; i < node.childNodes.length; i++) {
  83. if (!shouldIgnoreNode(node.childNodes[i])) {
  84. new_arr.push( parsePlistXML(node.childNodes[i]));
  85. }
  86. }
  87. return new_arr;
  88. } else if (node.nodeName === 'dict') {
  89. new_obj = {};
  90. key = null;
  91. counter = 0;
  92. if (isEmptyNode(node)) {
  93. return new_obj;
  94. }
  95. for (i=0; i < node.childNodes.length; i++) {
  96. if (shouldIgnoreNode(node.childNodes[i])) continue;
  97. if (counter % 2 === 0) {
  98. invariant(
  99. node.childNodes[i].nodeName === 'key',
  100. 'Missing key while parsing <dict/>.'
  101. );
  102. key = parsePlistXML(node.childNodes[i]);
  103. } else {
  104. invariant(
  105. node.childNodes[i].nodeName !== 'key',
  106. 'Unexpected key "'
  107. + parsePlistXML(node.childNodes[i])
  108. + '" while parsing <dict/>.'
  109. );
  110. new_obj[key] = parsePlistXML(node.childNodes[i]);
  111. }
  112. counter += 1;
  113. }
  114. if (counter % 2 === 1) {
  115. throw new Error('Missing value for "' + key + '" while parsing <dict/>');
  116. }
  117. return new_obj;
  118. } else if (node.nodeName === 'array') {
  119. new_arr = [];
  120. if (isEmptyNode(node)) {
  121. return new_arr;
  122. }
  123. for (i=0; i < node.childNodes.length; i++) {
  124. if (!shouldIgnoreNode(node.childNodes[i])) {
  125. res = parsePlistXML(node.childNodes[i]);
  126. if (null != res) new_arr.push(res);
  127. }
  128. }
  129. return new_arr;
  130. } else if (node.nodeName === '#text') {
  131. // TODO: what should we do with text types? (CDATA sections)
  132. } else if (node.nodeName === 'key') {
  133. if (isEmptyNode(node)) {
  134. return '';
  135. }
  136. return node.childNodes[0].nodeValue;
  137. } else if (node.nodeName === 'string') {
  138. res = '';
  139. if (isEmptyNode(node)) {
  140. return res;
  141. }
  142. for (i=0; i < node.childNodes.length; i++) {
  143. var type = node.childNodes[i].nodeType;
  144. if (type === TEXT_NODE || type === CDATA_NODE) {
  145. res += node.childNodes[i].nodeValue;
  146. }
  147. }
  148. return res;
  149. } else if (node.nodeName === 'integer') {
  150. invariant(
  151. !isEmptyNode(node),
  152. 'Cannot parse "" as integer.'
  153. );
  154. return parseInt(node.childNodes[0].nodeValue, 10);
  155. } else if (node.nodeName === 'real') {
  156. invariant(
  157. !isEmptyNode(node),
  158. 'Cannot parse "" as real.'
  159. );
  160. res = '';
  161. for (i=0; i < node.childNodes.length; i++) {
  162. if (node.childNodes[i].nodeType === TEXT_NODE) {
  163. res += node.childNodes[i].nodeValue;
  164. }
  165. }
  166. return parseFloat(res);
  167. } else if (node.nodeName === 'data') {
  168. res = '';
  169. if (isEmptyNode(node)) {
  170. return Buffer.from(res, 'base64');
  171. }
  172. for (i=0; i < node.childNodes.length; i++) {
  173. if (node.childNodes[i].nodeType === TEXT_NODE) {
  174. res += node.childNodes[i].nodeValue.replace(/\s+/g, '');
  175. }
  176. }
  177. return Buffer.from(res, 'base64');
  178. } else if (node.nodeName === 'date') {
  179. invariant(
  180. !isEmptyNode(node),
  181. 'Cannot parse "" as Date.'
  182. )
  183. return new Date(node.childNodes[0].nodeValue);
  184. } else if (node.nodeName === 'true') {
  185. return true;
  186. } else if (node.nodeName === 'false') {
  187. return false;
  188. }
  189. }