如何解析具有类似XML结构的文件,但内容旁边有自闭标签(而不是封闭内容)

时间:2017-03-23 21:44:21

标签: javascript node.js parsing xml-parsing domparser

我有一个以下结构的文件。它不是XML,但我需要以某种方式从中创建一个JSON。

所以虽然我希望该文件看起来像这样:

<chapter>
<line> Some text which I want to grab. </line>
<line> Some more text which I want to grab. </line>
<line> Even more text which I want to grab. </line>
</chapter>

实际上结构如下:

<chapter>
<line /> Some text which I want to grab.
<line /> Some more text which I want to grab.
<line /> Even more text which I want to grab.
</chapter>

所以&#39;&#39;每章只是站在自闭线标签旁边。你能推荐一种抓住这些的方法吗?可能在javascript / nodejs?

1 个答案:

答案 0 :(得分:2)

格式是有效的XML,因此您可以使用常规XML技术...即DOMParser来解析内容

但是,你只需要对解析这些行有点聪明 - 你想要找到每一行,并收集所有兄弟节点作为文本节点(应该只有一个,但我提供的代码不是做出任何假设)

你没有指定输出“结构”,但这里有一个你可以用来输出嵌套数组的方法 - 第一级是章节,每一章都有一个行数

var xml = `<chapter>
<line /> Some text which I want to grab.
<line /> Some more text which I want to grab.
<line /> Even more text which I want to grab.
</chapter>`

var parser = new DOMParser();
var content = parser.parseFromString(xml, 'application/xml')
var chapters = content.getElementsByTagName('chapter');
var obj = [].reduce.call(chapters, function(result, chapter) {
    var lines = chapter.getElementsByTagName('line');
    result.push([].reduce.call(lines, function(result, line) {
        var text = '';
        for(var node = line.nextSibling; node && node.nodeType == 3; node = node.nextSibling) {
            text += node.nodeValue;
        }
        result.push(text);
        return result;
    }, []))
    return result;
}, []);
console.log(JSON.stringify(obj));
  

解决评论 - 首先是一些文档:

DOMParse documentation

Array#reduce documentation

Function#call documentation

现在,在此代码中解释[].reduce.call(array, fn)

[].reduce.callArray.prototype.reduce.call

的简写

getElementsByTagName返回一个HTMLCollection ...其行为类似于一个数组,除了它不是一个......有几种方法可以从HTMLCollection中创建一个数组 - 最原始的:

var array = [];
for(var i = 0; i < collection.length; i++) {
    array[i] = collection[i];
}

var array = Array.prototype.slice.call(collection);

或(ES2015 +) - 除非您填充,否则在IE中不可用 - 请参阅文档

var array = Array.from(collection);

但是,在.call上使用[].reduce方法允许第一个参数(this参数)是任何可迭代的,而不仅仅是一个数组,所以它就像使用{{ 1}}从上面开始像array - 这是一种像处理数组一样处理HTMLcollection的方法,而不需要中间变量