XML to JSON - dealing with xml namespaces and alias in JavaScript
Asked Answered
E

4

11

I am trying to convert XML to JSON in node.js using the module xml2js. How do I handle the namespace alias when accessing variables?

The follow code converts my file (sampleWithNamespaces.xml)

var fs = require('fs'),
xml2js = require('xml2js');

var parser = new xml2js.Parser();
fs.readFile('sampleWithNamespaces.xml', function (err, data) {
    parser.parseString(data, function (err, result) {
        console.dir(result);
        console.log('Done');
    });
});

sampleWithNamespaces.xml :

<d:student xmlns:d='http://www.develop.com/student'>
  <d:id>3235329</d:id>
  <d:name>Jeff Smith</d:name>
  <d:language>JavaScript</d:language>
  <d:rating>9.5</d:rating>
</d:student>

Output:

$ node xml2jsTest.js
{ '@': { 'xmlns:d': 'http://www.develop.com/student' },
  'd:id': '3235329',
  'd:name': 'Jeff Smith',
  'd:language': 'JavaScript',
  'd:rating': '9.5' }
Done

I can access the 'name' attribute by using the notation result['d:name'] instead of result.name if I did not have the namespace alias. I guess my question is, am I doing this the right way?

I've read that "If an element has a namespace alias, the alias and element are concatenated using "$". For example, ns:element becomes ns$element" If I do this I can read the attribute as result.d$name. If I went this route, how would I got about doing so?

Empyreal answered 29/6, 2012 at 16:56 Comment(0)
H
8

I had a similar issue. Most of my XML tags were in a single namespace. So i decided to strip out all the namespaces from my XML.

It is possible to strip out namespaces while parsing XML by adding a tagNameProcessors to xml2js.

var parseString = require('xml2js').parseString;
var stripNS = require('xml2js').processors.stripPrefix;

parseString(xml_str, { tagNameProcessors: [stripNS] },function(err, result) {});

This will technically ignore all the namespace. If you have XML tags from multiple namespaces, then this might not be of great use.

Haemoid answered 20/2, 2017 at 16:31 Comment(1)
will this handle for a large file.Defective
S
4

For those who use typescript

  • add this import statement (you will need npm install -D @types/xml2js)
import { Parser, processors } from 'xml2js';
  • add tagNameProcessor option when create a new parser
    const parser = new Parser(
        {  
            trim: true,  
            explicitArray: false,
            tagNameProcessors: [processors.stripPrefix]
        });
        parser.parseString(xmlData, function(err, result)
        { 
Scrumptious answered 23/11, 2020 at 14:31 Comment(0)
C
1

if you use node and xml2js use result["ns:entry"] to refer to a specific entry

Courland answered 21/10, 2013 at 11:58 Comment(0)
C
0

The document you quote has nothing to do with xml2js, but you can get the same pattern if you want. You'd have to change the source code of xml2js or loop through renaming everything after loading it, both of which are not great ideas (the first means you won't be able to update so easily, and both add overhead to your code), so you should probably just stick to the ['d:name'] syntax. The only disadvantage is that it adds 3 characters to each lookup, but if your server uses gzip it won't make a difference in the real world.

If you really want to, this function will rename everything:

function colonToDollar(obj){
    var r={};
    for(var k in obj){
        r[k.replace(/:/g,'$')] = (typeof obj[k]==='object') ? colonToDollar(obj[k]) : obj[k];
    }
    return r;
}
Coconut answered 3/3, 2013 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.