Node.js - 帮助将XML转换为自定义JSON

时间:2014-05-28 19:18:26

标签: javascript xml json node.js

我正在构建一个xml到json函数,它将我们的XML结构转换为特定格式的JSON。

我已经尝试了很多库,最终,我已经决定只将XML转换为DOM树,我可以自己行走并转换为JSON,因为库不提供格式我需要。

所以这是一个示例xml文档:

var xml = '<document>' +
            '<divisions>' +
              '<division id="123" division="foo">' +
                '<departments>' +
                  '<department id="456" department="bar"/>'+
                  '<department id="678" department="bar"/>'+
                '</departments>' +
              '</division>' +
            '</divisions>' +

            '<roles>' +
              '<role id="123" name="foo"/>' +
              '<role id="123" name="foo"/>' +
            '</roles>' +
          '</document>';

期望的输出:

{ divisions: [ { id: '123', division: 'foo', departments: [ { id: '456', department: 'bar' } ] } ], roles: [ { id: '123', name: 'foo'}, { id: '123', name: 'foo'} ] }

这是我最初的努力:

var DOMParser = require('xmldom').DOMParser;

function XMLtoJSON(xml) {

  var json = {};
  var dom  = new DOMParser().parseFromString(xml).childNodes[0];

  function process(nodes, parent) {

    var node, name, hasChildren;

    for(var i = 0, l = nodes.length; i < l; i++) {

      node        = nodes[i];
      name        = node.tagName;
      hasChildren = node.hasChildNodes();

      if(!parent) {
        json[name] = [];
      }

      if(node.hasAttributes()) {

        var attributes = node.attributes, obj = {};
        for(var x = 0, al = attributes.length; x < al; x++) {

          obj[attributes[x].name] = attributes[x].value;

          if(!parent) {
            json[name].push(obj);
          }
        }
      }

      if(hasChildren) {
        process(nodes[i].childNodes);
      }
    }
  }

  process(dom.childNodes);

  return json;
}

console.log( XMLtoJSON(xml) );

目前,这将输出:

{ divisions: [],
  division: 
   [ { id: '123', division: 'foo' },
     { id: '123', division: 'foo' } ],
  departments: [],
  department: 
   [ { id: '678', department: 'bar' },
     { id: '678', department: 'bar' } ],
  roles: [],
  role: [ { id: '123', name: 'foo' }, { id: '123', name: 'foo' } ] }

注意:我不想要我的json中的父document,因此最初的parseFromString(xml).childNodes[0];

我想知道是否有人可以帮助我更近一点。具体来说,我无法解决如何处理嵌入式集合(部门是一个部门内的阵列)。我已经在这个工作了几个小时,递归让我一直在绊倒。

1 个答案:

答案 0 :(得分:0)

很抱歉,花了这么长时间才回答。这有点难。以下代码至少适用于您当前的示例XML。棘手的部分是决定哪些元素是数组,哪些元素不是。这里的逻辑是,所有带属性的东西都是对象,其他一切都是数组。

function DOMToObject (node, obj, isArray) {

    var child = node.firstChild,
        attributes,
        newObj,
        i,
        j,
        k = 0;

    if (!obj) {
        obj = {};
    }

    while (child) {

        attributes = child.attributes;

        if (attributes && attributes.length) {

            newObj = {};
            DOMToObject(child, newObj);

            for (i = 0, j = attributes.length; i < j; i++) {
                newObj[attributes[i].name] = attributes[i].value;
            }

        } else {

            newObj = [];
            DOMToObject(child, newObj, true);
        }

        if (isArray) {
            obj[k] = newObj;
            k += 1;

        } else {
            obj[child.nodeName] = newObj;
        }

        child = child.nextSibling;
    }

    return obj;
};

var JSON = JSON.stringify(DOMToObject(dom.firstChild));