API Docs for: 0.0.1
Show:

File: lib/parsers/xml.js

/*
 * niViz -- snow profiles visualization
 * Copyright (C) 2015 WSL/SLF - Fluelastrasse 11 - 7260 Davos Dorf - Switzerland.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

(function (niviz, DOMParser, document, Element) {
  'use strict';

  // --- Module Dependencies ---
  var Parser     = niviz.Parser;

  var literal    = niviz.util.literal;

  /** @module niviz */

  /**
   * An XML parser.
   *
   * @class XMLParser
   * @constructor
   *
   * @extends Parser
   *
   * @param {Array|String} data The data to parse.
   */
  function XMLParser(data) {
    Parser.call(this, data);
  }

  Parser.implement(XMLParser, 'xml');

  /**
   * This method needs to be implemented by all children of class Parser.
   * Parse the complete document and return the result.
   *
   * @method _parse
   * @protected
   * @return
   */
  XMLParser.prototype._parse = function () {
    try {
      var parser = new DOMParser();
      var xml    = parser.parseFromString(this.data, 'application/xml');

      if (xml.documentElement.nodeName === 'parseerror')
        throw new Error('failed to parse XML');

      this.document = xml.documentElement;
      this.parse_xml();

    } catch (error) {
      return this.emit('error', error);
    }

    this.end(); // emit the end event
    return this.result;
  };

  /**
   * @method parse_xml
   * @abstract
   */
  XMLParser.prototype.parse_xml = function () {
    throw new Error('not implemented');
  };

  /**
   * @method text
   * @param {Element|String} query
   * @param {Element} node
   * @return {String} The text content the node
   */
  XMLParser.prototype.text = function (query, node) {
    if (!node && typeof query !== 'string')
      node = query;
    else
      node = this.$(query, node);

    return literal(node && node.textContent || '');
  };

  /**
   * Get the node with a certain tag.
   *
   * @method $
   * @param {String} query
   * @param {Element} [node] Where to start query
   * @return {Element}
   */
  XMLParser.prototype.$ = function (query, node) {
    return scoped$query('querySelector', query, node || this.document);
  };

  /**
   * Get all the nodes with a certain tag.
   *
   * @method $
   * @param {String} query
   * @param {Element} [node] Where to start query
   * @return {Element}
   */
  XMLParser.prototype.$$ = function (query, node) {
    return scoped$query('querySelectorAll', query, node || this.document);
  };


  // --- Compatibility ---

  var scoped$query = (function () {
    try {
      document
        .createElement('div')
        .querySelectorAll(':scope *');

      return function scope$native(method, query, node) {
        return node[method](query);
      };

    } catch (error) {

      var SCOPE = /^:scope/i;

      return function scope$shim(method, query, node) {

        if (!SCOPE.test(query))
          return node[method](query);

        // We could create a temporary container here
        // but we don't need support this case!
        if (!node.parentNode)
          throw new Error(':scope selector on root node');

        // Must set both, in order for # selector to work in XML!
        if (!node.id) {
          node.id = 'id_' + (+new Date());
          node.setAttribute('id', node.id);
          node.setAttribute('kapustka', node.id);
        }

        return node.querySelector(query.replace(SCOPE, 'Layer[kapustka]'));
      };
    }
  }());

}(niviz, DOMParser, document, Element));