node.js xml2js:输出如何?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20238493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
xml2js: how is the output?
提问by DrakaSAN
I m trying to use the node.js module xml2js
我正在尝试使用 node.js 模块 xml2js
My code is quite simple:
我的代码很简单:
function testparse(pathname, callback) {
var parser = require('xml2js').Parser(),
util = require('util'),
fs = require('fs'),
fs.readFile(pathname, function (err, data) {
parser.parseString(data, function(err, result) {
console.log('Complete result:');
console.log(util.inspect(result, {depth: null})); //Work
console.log('Try to access element:');
console.log(result.smil.body); //Work
console.log(result.smil.body.update); //Undefined
});
});
}
My xml file is as:
我的xml文件是:
<?xml version="1.0"?>
<smil>
<head/>
<body>
<update /*some field*//>
<stream name="name"/>
<playlist /*some field*/>
<video /*some field*//>
<video /*some field*//>
<video /*some field*//>
</playlist>
</body>
</smil>
The output give me:
输出给我:
Complete result:
{ smil:
{ head: [''],
body:
[ { update: [[Object]],
stream: [[Object]],
playlist: [[Object]] } ] } }
Try to access element:
[Object]
Undefined
I have succeed in accessing body by trying, but now I m stuck, is there a template or example of how xml2js output the parsed xml somewhere?
我通过尝试成功访问了 body,但现在我卡住了,是否有模板或示例说明 xml2js 如何在某处输出解析的 xml?
采纳答案by DrakaSAN
For those who are wondering, xml2js use and abuse of array
对于那些想知道 xml2js 使用和滥用数组的人
For my file, the tree would be:
对于我的文件,树将是:
.result //Object
|_.head //Array
|_.body //Array
|_.update //Array
| |_.$ //Object
| |_.fields //Strings
|
|_.stream //Array
| |_.$ //Object
| |_.fields //Strings
|
|_.playlist //Array
|_.$ //Object
|_.fields //Strings
|
|_.video //Array
|_.$ //Object
|_.fields //Strings
回答by Garth Kidd
xml2jshas an un-enviable task: convert XML to JSON in a way that can be reversed, without knowing the schema in advance. It seems obvious, at first:
xml2js有一项令人羡慕的任务:以一种可以颠倒的方式将 XML 转换为 JSON,而无需事先知道架构。乍一看似乎很明显:
<name>Fred</name> → { name: "Fred" }
<chacha /> → { chacha: null }
Easy so far, right? How about this, though?
到目前为止很容易,对吧?不过这个怎么样?
<x><y>z</y><x>
Removing the human friendly names drives home the uncertainty facing xml2js. At first, you might think this is quite reasonable:
删除对人类友好的名称,将面临的不确定性带回家xml2js。一开始,你可能会觉得这很合理:
{ x: { y: "z" } }
Later, you trip over this XML text and realise your guessed-at schema was wrong:
稍后,您在此 XML 文本上绊倒并意识到您猜测的模式是错误的:
<x><y>z</y><y>z2</y></x>
Uh oh. Maybe we should have used an array. At least all the members have the same tag:
哦哦。也许我们应该使用数组。至少所有成员都有相同的标签:
{ x: [ "z", "z2" ] }
Inevitably, though, that turns out to be short-sighted:
然而,不可避免的是,事实证明这是短视的:
<x><y>z</y><y>z2</y><m>n</m>happy</x>
Uh...
呃...
{ x: [ { y: "z" }, { y : "z2" }, { m: "n" }, "happy" ] }
... and then someone polishes you off with some attributes and XML namespaces.
...然后有人用一些属性和 XML 命名空间来润色你。
The way to construct a more concise output schema feels obvious to you. You can infer details from the tag and attribute names. You understand it.
构建更简洁的输出模式的方法对您来说是显而易见的。您可以从标签和属性名称推断详细信息。你懂的。
The library does not share that understanding.
图书馆不同意这种理解。
If the library doesn't know the schema, it must either "use and abuse" arrays, extra layers of objects, special attribute names, or all three.
如果库不知道模式,它必须“使用和滥用”数组、额外的对象层、特殊属性名称或所有这三者。
The only alternative is to employ a variable output schema. That keeps it simple at first, as we saw above, but you'll quickly find yourself writing a great deal of conditional code. Consider what happens if children with the same tag name are collapsed into a list, but only if there are more than one:
唯一的选择是采用可变输出模式。正如我们在上面看到的那样,一开始就保持简单,但是您很快就会发现自己编写了大量条件代码。考虑一下如果具有相同标签名称的孩子被折叠成一个列表会发生什么,但前提是有多个:
if (Array.isArray(x.y)) {
processTheYChildren(x.y);
} else if (typeof(x.y) === 'object') {
// only one child; construct an array on the fly because my converter didn't
processTheYChildren([x.y]);
} else ...
TL;DR: it's harder than it looks. Read the Open311 JSON and XML Conversionpage for details of other JSON-side representations. All "use and abuse" arrays, extra layers of objects, members with names that didn't appear in the original XML, or all three.
TL;DR:这比看起来更难。阅读 Open311 JSON 和 XML 转换页面,了解其他 JSON 端表示的详细信息。所有“使用和滥用”数组、额外的对象层、名称未出现在原始 XML 中的成员,或所有三者。
回答by Clint Eastwood
As xml2js' documentation states, you can configure the parser to not abuse of arrays, by setting the property explicitArrayto false(important: it has to be a boolean value as the string "false"will just notwork!)
作为xml2js'文档状态,你可以配置解析器不滥用阵列,通过属性设置explicitArray来false(重要的是:它必须是一个布尔值作为字符串"false"只会不工作!)
Example:
例子:
var parser = new xml2js.Parser({explicitArray : false});
This way, you should be able to access your JSON properties in a much easier way. I hope this helps anyone.
这样,您应该能够以更简单的方式访问您的 JSON 属性。我希望这可以帮助任何人。
回答by Tristian
The JSON that comes back isn't too JavaScript friendly. I've written a helper function that can make it easier to work with.
返回的 JSON 对 JavaScript 不太友好。我编写了一个帮助函数,可以使它更容易使用。
Be sure to read it before using it so that you understand what it does.
请务必在使用前阅读它,以便您了解它的作用。
xml.parseString(xmlString, function(err, results){
if(err) throw err
results = cleanXML(results);
});
var cleanXML = function(xml){
var keys = Object.keys(xml),
o = 0, k = keys.length,
node, value, singulars,
l = -1, i = -1, s = -1, e = -1,
isInt = /^-?\s*\d+$/,
isDig = /^(-?\s*\d*\.?\d*)$/,
radix = 10;
for(; o < k; ++o){
node = keys[o];
if(xml[node] instanceof Array && xml[node].length === 1){
xml[node] = xml[node][0];
}
if(xml[node] instanceof Object){
value = Object.keys(xml[node]);
if(value.length === 1){
l = node.length;
singulars = [
node.substring(0, l - 1),
node.substring(0, l - 3) + 'y'
];
i = singulars.indexOf(value[0]);
if(i !== -1){
xml[node] = xml[node][singulars[i]];
}
}
}
if(typeof(xml[node]) === 'object'){
xml[node] = cleanXML(xml[node]);
}
if(typeof(xml[node]) === 'string'){
value = xml[node].trim();
if(value.match(isDig)){
if(value.match(isInt)){
if(Math.abs(parseInt(value, radix)) <= Number.MAX_SAFE_INTEGER){
xml[node] = parseInt(value, radix);
}
}else{
l = value.length;
if(l <= 15){
xml[node] = parseFloat(value);
}else{
for(i = 0, s = -1, e = -1; i < l && e - s <= 15; ++i){
if(value.charAt(i) > 0){
if(s === -1){
s = i;
}else{
e = i;
}
}
}
if(e - s <= 15){
xml[node] = parseFloat(value);
}
}
}
}
}
}
return xml;
};
Examples:
例子:
{
queries: { query: [ {}, {}, {} ] }
}
becomes
变成
{
queries: [ {}, {}, {} ]
}
and
和
{
types: { type: [ {}, {}, {} ] }
}
becomes
变成
{
types: [ {}, {}, {} ]
}
It will also safelyconvert integers/floating points.
它还可以安全地转换整数/浮点数。
Edit: Replaced for... in with for
编辑:替换为... in with for
回答by Stucco
You might want to try console.log(util.inspect(result, false, null)), which should display the whole result.
您可能想尝试console.log(util.inspect(result, false, null)),它应该显示整个结果。
回答by Guy
For me it was a console.dir issue or more accurately a non-issue.
对我来说,这是一个 console.dir 问题或更准确地说是一个非问题。
I had the same result when I console.dir the output:
当我 console.dir 输出时,我得到了相同的结果:
{
TextView: [ [Object] ],
ImageView: [ [Object] ] } }
But I was surprised to find out that it was a console.dir limitation and the data was actually there. Apparently console.dir does not show more than a few levels. When I console.dir a deeper level the data was there:
但我惊讶地发现这是 console.dir 限制,而且数据实际上就在那里。显然,console.dir 只显示几个级别。当我 console.dir 更深层次时,数据就在那里:
console.log(result.RelativeLayout.TextView);
output:
输出:
{ '$':
{ 'android:layout_width': 'wrap_content',
'android:layout_height': 'wrap_content',
'android:layout_marginLeft': '10dp',
'android:layout_marginTop': '10dp',
'android:textColor': '#ffffff',
'android:id': '@+id/textView',
'android:text': 'Hello World!' } }
I started looking for others libs only to go back and try again. If it helps anybody hurray.
我开始寻找其他库只是为了回去再试一次。如果它帮助任何人欢呼。

