All files / src xml2js.ts

86.96% Statements 40/46
50% Branches 4/8
87.5% Functions 7/8
85.71% Lines 36/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 891x   1x   1x                       1x         24x 24x 24x 24x 24x     195x 195x 195x     24x 191x 191x           207x 207x 207x   191x 191x 191x     24x 191x 191x     24x 3x     24x 1x     24x             24x 24x     24x       24x 24x         24x 24x      
import * as SAX from 'sax';
 
import { JsApi, Options } from './jsapi';
 
const saxOptions: SAX.SAXOptions = {
  trim: false,
  normalize: true,
  lowercase: true,
  xmlns: true,
  position: true,
};
 
/**
 * @param {String} data input data
 * @param {Function} callback
 */
export function xml2js(
  data: string,
  onSuccess: (jsApi: JsApi) => void,
  onFail: (error: string) => void,
) {
  const sax = SAX.parser(true, saxOptions);
  const root = new JsApi({ elem: '#document', content: [] });
  let current: JsApi = root;
  const stack = [root];
  let parsingError = false;
 
  function pushToContent(options: Options) {
    const newContent = new JsApi({ parentNode: current, ...options });
    (current.content = current.content || []).push(newContent);
    return newContent;
  }
 
  sax.onopentag = function(node) {
    const qualifiedTag = node as SAX.QualifiedTag;
    const elem = {
      elem: qualifiedTag.name,
      prefix: qualifiedTag.prefix,
      local: qualifiedTag.local,
      attrs: {} as any,
    };
    for (const name of Object.keys(qualifiedTag.attributes)) {
      const { value, prefix, local } = qualifiedTag.attributes[name];
      elem.attrs[name] = { name, value, prefix, local };
    }
    const jsApiElem = pushToContent(elem);
    current = jsApiElem;
    stack.push(jsApiElem);
  };
 
  sax.onclosetag = function() {
    stack.pop();
    current = stack[stack.length - 1];
  };
 
  sax.oncomment = function(comment) {
    pushToContent({ comment: { text: comment.trim() } });
  };
 
  sax.onprocessinginstruction = function(processingInstruction) {
    pushToContent({ processingInstruction });
  };
 
  sax.onerror = function(error) {
    error.message = 'Error in parsing SVG: ' + error.message;
    if (error.message.indexOf('Unexpected end') < 0) {
      throw error;
    }
  };
 
  sax.onend = function() {
    Iif (this.error) {
      onFail(this.error.message);
    } else {
      onSuccess(root);
    }
  };
 
  try {
    sax.write(data);
  } catch (e) {
    onFail(e.message);
    parsingError = true;
  }
  Eif (!parsingError) {
    sax.close();
  }
}