Parse, Edit, & Write Changes to XML Files With Node.js
This article will show you how to read, parse and make updates to an Extensible Markup Language (XML) file with Node.js. We'll be using the xml2json NPM package to parse the XML.
Let's get started!
Table of Contents
What is XML?
XML is a markup language (HTML is also a markup language) that gives a set of rules for encoding files in a format that can be read efficiently by both humans and machines. It was designed with simplicity and usability.
Its most widely used application is for sitemaps. Sitemaps are used to tell search engines about the pages and structure of a website. These are commonly written in XML because it is easy to use and easy for Google and Bing's search engines to read and parse the data.
That was a quick and dirty explanation of XML. If you want more information, here are some good sources for you to check out:
Set Up Project
Before we start writing code, let's set up our project folder.
Above anything else, you'll need Node.js installed if you don't have it already.
If you need one, we created a guide on installing Node.js.
Create Project Folder
Let's quickly create a directory for our code:
mkdir xml-nodejs
And then cd
into your new directory:
cd xml-nodejs
NPM Init & Install Dependencies
Next, run npm init
to create a package.json
file that will hold the configuration for our code:
npm init
Then you can install the xml2json and xml-formatter packages we will be using later on:
npm install xml2json xml-formatter --save
Create Index.js File
Next, create the index.js
file where the meat of our code will reside:
touch index.js
We will come back to this file later. But for now, you can keep it empty.
Next, create an XML file in the root of your project that we will use for testing purposes:
touch data.xml
And fill the file with this XML content:
<breakfast_menu>
<food id="1">
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
</food>
<food id="2">
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>Light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
</food>
<food id="3">
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
</food>
</breakfast_menu>
We now have a project setup with a test XML file. Now we are ready to start parsing and editing our XML file.
Parse The XML File
First, let's read the data.xml
file, which should be in the root
directory of your folder. All we need to do is import the fs
package and use the readFile
function.
Open your index.js
file and add the following code to it:
const fs = require("fs")
const xmlParser = require("xml2json")
fs.readFile( "./data.xml", function(err, data) {
const xmlObj = xmlParser.toJson(data, {reversible: true, object: true})
console.log(xmlObj)
})
The first two lines of the file import the fs
and xml2json
NPM packages for use. Then, we use the fs.readFile
to read the XML file and return its data. Once we have the XML data, we use the xml2json
package to transform the XML into a JavaScript object.
The reversible
option will allow us to switch the object back to XML later on. And the object
option returns the XML as a JavaScript object instead of a JSON string. And the console.log
line will print the result to the command line.
To test the code, run the node index.js
command:
node index.js
You should see an output similar to this:
{ breakfast_menu: { food: [ [Object], [Object], [Object] ] } }
Make Edits to the XML Object
We are now ready to make edits to the xmlObj
. For testing purposes, lets find the food item with an id
value equal to "3"
and update its name to something different.
To acheive this, make the following updates to the conents of the index.js
file:
const fs = require("fs")
const xmlParser = require("xml2json")
fs.readFile( "./data.xml", function(err, data) {
const xmlObj = xmlParser.toJson(data, {reversible: true, object: true})
const foodItemsArray = xmlObj["breakfast_menu"]["food"]
for (let i = 0; i < foodItemsArray.length; i++) {
if (foodItemsArray[i].id === "3") {
xmlObj["breakfast_menu"]["food"][i].name.$t = "Belgian Waffles with Assorted Berries"
}
}
})
The first thing we added is a foodItemsArray
that holds the array of objects of all the food items. Then, we loop through each of the food items and update the name of the item with an id
of "3"
.
Write Changes to The XML File
Now we are ready to write the changes to the data.xml
file using the fs
module again.
Update the index.js
file to look like this:
const fs = require("fs")
const xmlParser = require("xml2json")
const formatXml = require("xml-formatter")
fs.readFile( "./data.xml", function(err, data) {
const xmlObj = xmlParser.toJson(data, {reversible: true, object: true})
const foodItemsArray = xmlObj["breakfast_menu"]["food"]
for (let i = 0; i < foodItemsArray.length; i++) {
if (foodItemsArray[i].id === "3") {
xmlObj["breakfast_menu"]["food"][i].name.$t = "Belgian Waffles with Assorted Berries"
}
}
const stringifiedXmlObj = JSON.stringify(xmlObj)
const finalXml = xmlParser.toXml(stringifiedXmlObj)
fs.writeFile("./data.xml", formatXml(finalXml, {collapseContent: true}), function(err, result) {
if (err) {
console.log("err")
} else {
console.log("Xml file successfully updated.")
}
})
})
We just made several changes to our index.js
file so let's go over them.
First, we added a new package called xml-formatter
that will be used to format the XML we write to the file later on in our code. Next, we created the stringifiedXmlObj
variable that transforms our xmlObj
into a JSON string. And we created our finalXml variable by using xml2json
package to switch the JSON back into an XML string.
At this point, we have the new XML data we want to write to the data.xml
file. So, we then use the fs
package to write the new XML data to the file. Notice we use the xml-formatter
package to make our xml data more human-readable.