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