11

Let's say I have the following xml code

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<catalog>
  <person>
    <name>John</name>
    <surname>Smith</surname>
  </person>
  <person>
    <name>Abe</name>
    <surname>Lincoln</surname>
  </person>
  <person>
    <name>James</name>
    <surname>Bond</surname>
  </person>
</catalog>

And I want to add a new node, let's say the following:

<person>
  <name>Tony</name>
  <surname>Stark</surname>
</person>

How do I do this in node js? I mean I have a file (/routes/index.js in node js express, to be exact), and I want to be able to add/modify existing xml file. I've tried fs.writeFile(), but this writes a whole new file, and fs.appendFile() adds a header(?xml + encoding and stuff) and root nodes after the last node, so I can't insert it into the catalog node. I can't get rid of the xml declaration header either.
I've been using .builder() to do this, and it looked like this

router.post('/addnode', function (req, res) {

  var obj = {name: "Tony", surname: "Stark"};
  var fs = require('fs');
  var xml2js = require('xml2js');

  var builder = new xml2js.Builder();
  var xml = builder.buildObject(obj);  

  fs.writeFile('public/test.xml', xml, function (err) {
    if (err) throw err;
    console.log('It\'s saved!');
  }); 
});

Finally I want to get that data from a from addnode, so I won't create a var obj in this function.

2 Answers 2

9

You can use a third-party library like xml2js, xml-js or xml-parse.

Let's say you have data variable with your xml code:

let data = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<catalog>
  <person>
    <name>John</name>
    <surname>Smith</surname>
  </person>
  <person>
    <name>Abe</name>
    <surname>Lincoln</surname>
  </person>
  <person>
    <name>James</name>
    <surname>Bond</surname>
  </person>
</catalog>`;
  1. xml2js
const xml2js = require('xml2js');
xml2js.parseString(data, (err, result) => {
  result.catalog.person.push({ name: 'Tony', surname: 'Stark' });
  const builder = new xml2js.Builder();
  data = builder.buildObject(result);
  // write data to file
});
  1. xml-js
const convert = require('xml-js');
const result = convert.xml2js(data, { compact: true });
result.catalog.person.push({ name: { _text: 'Tony' }, surname: { _text: 'Stark' } });
data = convert.js2xml(result, { compact: true, spaces: 2 });
// write data to file
  1. xml-parse
const xml = require('xml-parse');
let result = xml.parse(data);
result.find(n => n.tagName === 'catalog').childNodes.push({
  type: 'element',
  tagName: 'person',
  childNodes: [{
    type: 'element',
    tagName: 'name',
    childNodes: [{
      type: 'text',
      text: 'Tony'
    }]
  }, {
    type: 'element',
    tagName: 'surname',
    childNodes: [{
      type: 'text',
      text: 'Stark'
    }]
  }],
});
data = xml.stringify(result, 2);
// write data to file
Sign up to request clarification or add additional context in comments.

Comments

7

Unless the files' sizes are unacceptable and you cannot read them as a whole, you can use xml2js and never work with XML.

By using it, you can read the file, convert it in an object which is far easier to manipulate, add your stuff there and then convert it back as XML and write the result again on the original file.

Looking at your example, you create a new object and append it to the the file. Instead, you should read the already existent data and modify them, then write everything back (do not append them) to the file. To do that, you have to use the Parser object from xml2js.

3 Comments

And how do I modify the json object? I do indeed have the xml's content parsed into json object and display it somewhere else, so I know how to overwrite existing xml with json, but I'm not sure how to add something to json object, especially when the content I want to add have to be nested inside inner nodes. I load the data using fs.readFileSync.
The way xml2js creates an object starting from XML is well documented (see library reference). It's also pretty intuitive and if you have problems you can still open another question on stackoverflow. ;-)
Note that xml2js parser don’t preserve the order of the XML which might be important in many cases. A more reliable solution would be xmldom.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.