parser.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. 'use strict';
  2. const xml2js = require('xml2js');
  3. const stripNS = xml2js.processors.stripPrefix;
  4. const parser = new xml2js.Parser({
  5. tagNameProcessors: [stripNS],
  6. // xmlns: true,
  7. explicitChildren: true,
  8. });
  9. const parseXML = input => parser.parseStringPromise(input);
  10. function childAttr(obj, key, errorCode = 452) {
  11. const value = obj[key];
  12. if (value === undefined || value.length === 0) {
  13. return undefined;
  14. }
  15. if (value.length !== 1) {
  16. const error = new Error(`Invalid attribute: ${key}`);
  17. error.errorCode = errorCode;
  18. throw error;
  19. }
  20. if (value[0]['$$']) {
  21. // there is a child element
  22. return value[0];
  23. }
  24. if (value[0]['$']) {
  25. if (value[0]['_']) {
  26. return value[0]['_']; // namespaced text node
  27. }
  28. return ''; // namespaced, no text between tags
  29. }
  30. return value[0]; // un-namespaced text node
  31. }
  32. function boolean(input, errorCode = 452) {
  33. const trimmed = (input || '').toLowerCase().trim();
  34. if (trimmed === '') {
  35. return undefined;
  36. } else if (trimmed === 'true' || trimmed === '1') {
  37. return true;
  38. } else if (trimmed === 'false' || trimmed === '0') {
  39. return false;
  40. }
  41. const error = new Error(`Not a boolean: ${input}`);
  42. error.errorCode = errorCode;
  43. throw error;
  44. }
  45. function dateTime(input, key, errorCode = 452) {
  46. if (input) {
  47. if (input['$$']) {
  48. return childAttr(input['$$'], key, errorCode);
  49. }
  50. throw new Error(`unknown dateTime: ${input}`);
  51. }
  52. }
  53. function duration(input, key, errorCode = 452) {
  54. if (input) {
  55. if (input['$$']) {
  56. return childAttr(input['$$'], key, errorCode);
  57. }
  58. throw new Error(`unknown duration: ${input}`);
  59. }
  60. }
  61. function number(input, errorCode = 452) {
  62. const trimmed = (input || '').toLowerCase().trim();
  63. const parsed = Number(trimmed);
  64. if (trimmed === '') {
  65. return undefined;
  66. } else if (isNaN(parsed)) {
  67. const error = new Error(`Not a number: ${input}`);
  68. error.errorCode = errorCode;
  69. throw error;
  70. } else {
  71. return parsed;
  72. }
  73. }
  74. function required(input, key, errorCode = 452) {
  75. if (input == null) {
  76. const error = new Error(`Missing required value: ${key}`);
  77. error.errorCode = errorCode;
  78. throw error;
  79. }
  80. return input;
  81. }
  82. module.exports = {
  83. parseXML,
  84. childAttr,
  85. dateTime,
  86. duration,
  87. boolean,
  88. required,
  89. number,
  90. };