xmldom icon indicating copy to clipboard operation
xmldom copied to clipboard

Need example to traverse and modify XML file using XMLDOM

Open vipulsjoshi opened this issue 10 years ago • 14 comments

I am new to Node.js and am trying to parse, traverse and modify a XML (KML) file using Node.js. Can someone please provide an example on how to use the XMLDOM library to do this? Thanks in advance.

VJ

vipulsjoshi avatar Sep 23 '14 12:09 vipulsjoshi

Open the file as a string using fs.readFile: http://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback

Then use xmldom to parse the XML into a DOM object using DOMParser.parseFromString: https://github.com/jindw/xmldom#api-reference

When you do that you'll have a DOM object you can traverse with common DOM methods like getElementsByTagName and the like.

You can use those to find elements and make whatever changes you like to them. Once you're done, you can convert the document back into a string using xmldom's XMLSerializer.serializeToString and then write the file back to disk using fs.writeFile: http://nodejs.org/api/fs.html#fs_fs_writefile_filename_data_options_callback

kethinov avatar Sep 23 '14 12:09 kethinov

Thanks Kethinov!

vipulsjoshi avatar Sep 24 '14 07:09 vipulsjoshi

I am trying to read multiple xml files from a dir and traverse and parse them. I have it working with a single file, can someone suggest the some options to read multiple files from a dir in Node.js?

Thanks in advance. VJ

vipulsjoshi avatar Sep 26 '14 12:09 vipulsjoshi

Loop through the directory and open each file like in the example above.

kethinov avatar Sep 26 '14 14:09 kethinov

As mentioned above. I am trying to read modify write and XML tag element value. fs.readFile('./test.xml','utf8', function (err, data) { if (err) { return console.log(err); } else { var doc = new dom().parseFromString(data); doc.getElementsByTagName("status")[0].childNodes[0].nodeValue = '100'; console.log(doc.getElementsByTagName("status")[0].childNodes[0].nodeValue); //Return correct value 100

        var serializer = new xmldom.XMLSerializer();
        var writetofile = serializer.serializeToString(doc);
        console.log(writetofile);  //Returns WRONG old value.   

}

Am I missing something ?

Thanks in advance.

youemailmee avatar Mar 12 '15 07:03 youemailmee

Here's a full working example:

first I went to https://msdn.microsoft.com/en-us/library/ms762271%28v=vs.85%29.aspx and saved that xml as books.xml

then I wrote this simple node program using fs and xmldom:

var xmldom = require('xmldom').DOMParser,
    fs = require('fs');

fs.readFile('books.xml', 'utf-8', function (err, data) {
  if (err) {
    throw err;
  }
  var genreno,
      thisgenreobject,
      thisgenre,
      doc,
      genres;
  doc = new xmldom().parseFromString(data, 'application/xml');
  genres = doc.getElementsByTagName('genre');
  for (genreno in genres) {
    thisgenreobject = genres[genreno];
    if (thisgenreobject.firstChild) {
      thisgenre = thisgenreobject.firstChild.nodeValue;
      if (thisgenre === 'Computer') {
        console.log(thisgenreobject.parentNode.getElementsByTagName('title')[0].firstChild.nodeValue);
      }
    }
  }
});

This returns the names of all the computer books from the sample data set.

Autre31415 avatar Mar 14 '15 18:03 Autre31415

I'm seeing the same effect as youemailmee, where i can modify the nodes, the value appears to have changed, but when using XMLSerializer().serializeToString(doc) the output string contains the old value.

Anyone know what I am missing?

xenobytezero avatar Apr 16 '15 01:04 xenobytezero

Same here! This code returns the exact same XML that went in, without the modification

var DOMParser = require('xmldom').DOMParser;
var XMLSerializer = require('xmldom').XMLSerializer;
var serializer = new XMLSerializer();
var doc = new DOMParser().parseFromString(
    '<xml xmlns="a" xmlns:c="./lite">\n'+
        '\t<child>test</child>\n'+
        '\t<child></child>\n'+
        '\t<child/>\n'+
    '</xml>'
    ,'text/xml');
var xpath = require('xpath');
var select = xpath.useNamespaces({a: 'a'});
var node;

node = select('//a:child', doc, true);
console.info('selected node', node.toString());

node.firstChild.text = 'changed';
node.firstChild.nodeValue = 'changed';
node.text = 'changed';
node.nodeValue = 'changed';
console.info('new node', node.firstChild.nodeValue);
console.info('doc after change', serializer.serializeToString(doc))

soujiro32167 avatar May 21 '15 19:05 soujiro32167

Got it to change text! Used the node.textContent attribute

var DOMParser = require('xmldom').DOMParser;
var XMLSerializer = require('xmldom').XMLSerializer;
var serializer = new XMLSerializer();
var doc = new DOMParser().parseFromString(
    '<xml xmlns="a" xmlns:c="./lite">\n'+
        '\t<child>test</child>\n'+
        '\t<child></child>\n'+
        '\t<child/>\n'+
    '</xml>'
    ,'text/xml');
var xpath = require('xpath');
var select = xpath.useNamespaces({a: 'a'});
var node;

node = select('//a:child', doc, true);
console.info('selected node', node.toString());

//node.firstChild.text = 'changed';
//node.firstChild.nodeValue = 'changed';
//node.text = 'changed';
//node.nodeValue = 'changed';
node.textContent = 'changed';
console.info('new node', node.firstChild.nodeValue);
console.info('doc after change', serializer.serializeToString(doc))

soujiro32167 avatar May 21 '15 19:05 soujiro32167

HI friends.... i have solved the issue ....cheers....... you can check my code


parseXML : function () { try { var xml = fs.readFileSync(process.env.PWD+"/upload/tmp/filtered.xml").toString();// fetch xml and convert to string var DOMParser = require('xmldom').DOMParser; var dom = new DOMParser().parseFromString(xml); var XMLSerializer = require('xmldom').XMLSerializer; var serializer = new XMLSerializer();

dom.documentElement.firstChild.nextSibling.attributes[0].nodeValue = "kissing" console.log(dom.documentElement.firstChild.nextSibling.attributes[0].nodeValue);

var newString = ''+ ''+ ''+"Everyday Italian"+''+ ''+"Giada De Laurentiis"+''+ ''+"2005"+''+ ''+"30.00"+''+''+ ''; var newDom = new DOMParser().parseFromString(newString); fs.writeFileSync(process.env.PWD+"/upload/tmp/filtered-res.xml",serializer.serializeToString(newDom));

} catch (error) { console.log("error in catch ---"); console.log(error); } }

tulsirampalavalasa avatar Aug 23 '16 13:08 tulsirampalavalasa

I am not able to modify my xml using XMLSerializer... My code is var xml= request.responseText; var DOMParser = require('xmldom').DOMParser; var parser = new DOMParser(); var document = parser.parseFromString(xml, 'text/xml'); document.getElementsByTagName("a:Value").nodeValue=12345; var XMLSerializer = require('xmldom').XMLSerializer; var serializer = new XMLSerializer(); var writetofile = serializer.serializeToString(document); console.log("writetofile"+writetofile);

I am getting XML with same old value not 12345.

Please let me know how to resolve this..tried all above options..still not working.:(

nitsb avatar Oct 28 '16 09:10 nitsb

Hi, everyone, how can i get the raw data: <a> <result>true</result> </a> I want the the raw data: <result>true</result>. how should i do?

cool-firer avatar Mar 14 '17 07:03 cool-firer

i can not modify XML file,what is wrong? please help me

var fs = require("fs"); var DOMParser = require('xmldom').DOMParser; var XMLSerializer = require('xmldom').XMLSerializer; var serializer = new XMLSerializer(); fs.readFile('./noauth-config.xml','utf8', function (err, data) { if (err) { return console.log(err); } else{ var doc = new DOMParser().parseFromString(data,'application/xml') var genres = doc.getElementsByTagName('config')[0]; // 克隆一个节点 newNode=genres.cloneNode(true); // 将克隆的节点追加到最后 doc.documentElement.appendChild(newNode); console.log("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); // 获取待修改的目标属性的值 console.log(doc.documentElement.lastChild.childNodes[1].attributes[1].nodeValue); console.log(doc.documentElement.lastChild.attributes[0].nodeValue); // 修改目标属性的值 doc.documentElement.lastChild.childNodes[1].attributes[1].nodeValue = "1.1.1.1"; doc.documentElement.lastChild.attributes[0].nodeValue = "ttttttttttttttttttt"; console.log(doc.documentElement.lastChild.childNodes[1].attributes[1].nodeValue); console.log(doc.documentElement.lastChild.attributes[0].nodeValue); console.log(serializer.serializeToString(doc)); });

zhangjianpinghik avatar Jun 09 '17 06:06 zhangjianpinghik

For anyone else struggling with this, you need to change the .data value on the child node and not .nodeValue. see: https://stackoverflow.com/a/32854062

mhilland avatar Feb 22 '18 23:02 mhilland