Node.js Xml2js result from attribute

What am I doing wrong? I cannot get the tag value inside the child attribute. Here is my xml:

<root> <time c="00:00:00"> <title>Title</title> <text>Some Text...</text> </time> <time c="00:00:01"> <title>Title 2</title> <text>Some text...</text> </time> </root> 

This is what I did in node:

 xml2js = require('xml2js'); fs = require('fs'); var parser = new xml2js.Parser(); var timetag = '00:00:01'; fs.readFile( 'test.xml', function(err, data) { parser.parseString(data, function (err, result) { function sendSubs() { io.sockets.emit('subs', { subs: result.root.time[c=timetag].title }); } setInterval(sendSubs, 1000); }); }); 

I’m sure the problem is with the syntax, but I don’t see it !, and is it possible to get the values ​​of two children, such as the name and the text?

Hi

+7
javascript xml
source share
2 answers

The syntax you use allows you to navigate through the nodes of a JSON object. But it looks like you are trying to find it as an XPath predicate. This will not work.

Using xml2js, you can get an array of time objects in your code using:

 result.root.time 

And then, a loop comparing the value of $.c as you reach the attributes. For example, the attribute of the second time element:

 result.root.time[1].$.c 

So, the data you need to compare with your field. When you find out which element of the time array it is in, you get a title (actually a singleton array containing the header), like this:

 var resultArr = []; for(var i = 0; i < result.root.time.length; i++) { if (result.root.time[i].$.c == timetag) { resultArr = result.root.time[i].title; break; } } 

What you can send to your socket:

 io.sockets.emit('subs', { subs: resultArr[0] }); 

Solution Using JSONPath

If you don't want to implement a loop in JavaScript to compare attribute values, you can use JSONPath. This syntax is not as good as XPath, but it works. You will need to get it through NPM and require:

 var jsonpath = require('JSONPath'); 

And then you can get a title with this expression:

 var expression = "$.root.time[?(@.$.c == '00:00:01')].title[0]"; 

[..] is a predicate ? should run a script with the expression, @. is access to the attribute (which is represented in the xml2js object as $.c . line with your timetag variable.

To search, use:

 var resultArr = jsonpath.eval(result, expression); 

An array containing the desired text will be returned. Then you can send it wherever you want:

 io.sockets.emit('subs', { subs: resultArr[0] }); 

You can learn more about JSONPath here: http://goessner.net/articles/JsonPath/

+10
source share

When converting XML to JSON, xml2js maps the attributes to '$'. In case your key name does not match the name of the child key. You can combine attributes with Child elements. If your JSON looks clean.

xml2js.Parser ({ignoreAttrs: false, mergeAttrs: true})

You can solve your problem.

0
source share

All Articles