0

I have a question on same module as I posted last time in below post. Seems like, it is quite difficult to deal with XML parsing. With elementTree having very mearge documentation.

I have a below template_XML file:

<?xml version="1.0" encoding="UTF-8"?>
<Tailoring xmlns="http://checklists.nist.gov/xccdf/1.2" id="xccdf_org.open-scap_tailoring_example">
<status>incomplete</status>
<version time="2013-01-15T16:00:00.000+02:00">1.0</version>
    <Profile id="PlaceHolder">
    <title>Tailoring for py_test</title>
    <select idref="xccdf_rule_name" selected="true"/>
</Profile>
</Tailoring>

And a below sample_XML file:

<Benchmark xmlns="http://checklists.nist.gov/xccdf/1.1" xmlns:xsi="www.w3.org/2001/XMLSchema-instance" id="SAP-HANA" resolved="1" xml:lang="en-US">
<status date="2016-03-17">draft</status>
<title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US">Guide to the Secure Configuration of SAP HANA</title>
<version>0.1.28</version>

<Profile id="profile1">
    <title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US">text1</title>
    <select idref="This is rule 1" selected="true"/>
    <set-value idref="ssfs_master_key_timeout">20</set-value>
</Profile> 

<Profile id="profile2">
    <title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US">text2</title>
    <select idref="this is rule1" selected="true"/>
    <select idref="this is rule1" selected="true"/>
    <select idref="this is rule1" selected="true"/>
</Profile>
</Benchmark>

I need to create a new_xml file, a copy of template_XML file. But want to replace "PlaceHolder" profile tag in new_xml file with the "profile2" tag of sample_XML file. Its a kind of merging of 2 xml file and creating a new one. Below is the code I have tried:

function call(id){
    var template_XML = 'C:\\MyDrive\\template_XML';
    var new_xml = 'C:\\MyDrive\\new_xml';
    data = fs.readFileSync(template_XML).toString();
    data1 = fs.readFileSync(sample_XML).toString();
    etree = et.parse(data);
    etree1 = et.parse(data1);
    var profile = etree.find('./Profile');  // Getting the profile sub-element.
    etree.getroot().remove(profile)         // Removing the sub-element. So that I can insert new profile from sample file

    var profiles = etree1.findall('./Profile'); // Find the required profile.
    for (var i = 0; i < profiles.length; i++) {
        if(profiles[i].get('id') == 'profile2')
            var tmppro = profiles[i];
    }
    console.log(tmppro);
    etree.insert(3,tmppro);     // insert it. Failing

    var write = fs.openSync(new_xml, 'w');
    etree.write(write);                     // write it. Failing
}

For one or the other reason, this code is not working in terms of "etree.insert" and "etree.write"

Hemant Yadav
  • 307
  • 1
  • 4
  • 19

1 Answers1

1

Finally I was able to make it working with current lib. Please see my comments:

'use strict';

const et = require('elementtree');
const path = require('path');
const fs = require('fs');

function populateXmlTemplate(id) {
 //Please use path.join to make it cross-platform
 var template_XML = path.join(__dirname, 'template.xml');
 var sample_XML = path.join(__dirname, 'sample.xml');
 var new_xml = path.join(__dirname, 'new.xml');

 var data = fs.readFileSync(template_XML).toString();
 var data1 = fs.readFileSync(sample_XML).toString();

 var etree = et.parse(data);
 var etree1 = et.parse(data1);

 var root = etree.getroot();

 var placeholder = root.find('./Profile');
 root.remove(placeholder);

 var profiles = etree1.findall('./Profile'); // Find the required profile.
 for (var i = 0; i < profiles.length; i++) {
  //If I get it right, it shouldn't be hardcoded
  if (profiles[i].get('id') == id) {
   var tmppro = profiles[i];
  }
 }

 //After you removed the placeholder the number of children decreased
 //So it should be 2, not 3.
 //Also etree doesn't have insert method, please call root.insert
 root.insert(2, tmppro);

 //You have been writing the document a bit incorrectly.
 var resultXml = etree.write();
 fs.writeFileSync(new_xml, resultXml);
}

populateXmlTemplate('profile2');

module.exports = {populateXmlTemplate};

But you're right, the documentation is not good. It's mostly missing. So mostly I simply have been debugging it to see the available methods, also there are some tests in the lib repo.

There are other modules to work with js. Please see this answer.

Community
  • 1
  • 1
Antonio Narkevich
  • 4,206
  • 18
  • 28
  • Thanks a ton Antonio, WebStorm will help me a lot in writing further application. In fact I was not aware of any IDE for nodejs application. populateXmlTemplate() is throwing below stack trace, but now its OK, I will handle the situation by debugging it in IDE. etree.write(); // TypeError: Cannot read property 'iter' of undefined It seems I need +15reputation to upvote an answer, however my upvote is noted. :) – Hemant Yadav Mar 03 '17 at 09:30
  • Hi Antonio, any idea if I can copy the comment also. For example if tag contains comments . ETREE is not copying the comments section from sample_XML profile into the new_xml file. – Hemant Yadav Jun 13 '17 at 09:25