1

i am trying to read an attribute value from xml using nodejs code snippet and below is my xml Data. Trying to fetch environment QA or UAT. I wrote the code to parse the xml. Now the challenge is not able to understand this output format of console.log. Not sure which API have to be used get/read "name" attribute value.

Please help me to read the value of name attribute.

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="QA" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="QA2" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="UAT" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="UAT2" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="SandBox" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="SandBox" ></testsuite>
</testsuites>

`

const fs = require("fs");
const path = require("path")
const xml2js = require("xml2js")

let files;
let htmlobj = '<h3>Summary</h3><table><tr><th>Error Count</th></tr>'
files = fs.readdirSync(__dirname);
var parser = new xml2js.Parser();
let filecount = 0;
let counter = 0;
const junitfiles = {};
files.forEach(file => {
            if (path.extname(file) != ".xml") return;
                const extname = path.extname(file);
                const filename = path.basename(file, extname);
                const obsolutePath = path.resolve(__dirname, file); 
                fs.readFile(obsolutePath, function(err, data) {
                        if (err) {
                            console.log('error in readFile', err);
                        } else {
                            parser.parseString(data, function(err, result) {
                                if (err) {
                                    console.log('error parsing', err)
                                }
                             else {
                                let resultvalue = 0;
                                let envcount = 0;
                                for (var i = 0; i < result.testsuites.testsuite.length; i++) {
                                    resultvalue = result.testsuites.testsuite[i];
                                    console.log('value of testsuite object', resultvalue);
                                }
                            }
                        });
                        }
                });
});

`

Output of Node js code

value of testsuite object { '$': { name: 'QA' } }
value of testsuite object { '$': { name: 'QA2' } }
value of testsuite object { '$': { name: 'UAT' } }
value of testsuite object { '$': { name: 'UAT2' } }
value of testsuite object { '$': { name: 'SandBox' } }
value of testsuite object { '$': { name: 'SandBox' } }

2 Answers 2

1

To answer your question:

Add below console.log('value of testsuite object', resultvalue);

const attributeName = resultvalue.$.name
console.log('value of attribute name is ', attributeName)

On another note: Be carefull with .forEach and callbacks, you're not gonna get the information in the correct order, since its async code.

The order you think your code is running

  1. Go through files
  2. Loop through file nr 1
  3. Read file nr 1
  4. Console log contensts of file nr 1
  5. Loop through file nr 2 ..etc, etc.

But callbacks are like the name suggest "call me back, when you're ready" - so its not gonna console log anything until it has read the file. Meanwhile the loop still continues, so you could have something like

  1. Go through files
  2. Loop through file nr 1
  3. Read file nr 1
  4. Loop through file nr 2
  5. Console log contensts of file nr 1 ..etc, etc.

see how items 4 og 5 switched.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks @Bergur ....that $ trick woked
Good to hear. If you're happy I would appreciate you marking it as a correct answer.
what is the trick with $. Now i have a slight different output in console? additional [] braces in console. like below value of testsuite object [{ '$': { name: 'QA' } }] value of testsuite object [{ '$': { name: 'QA2' } }] when i am trying to use resultvalue.$.name, script throws error saying TypeError: Cannot read properties of undefined (reading 'name')
There is no trick, its how the xml2js module is designed. $ is for attributes on elements and _ is for the value/inner text. You can edit this by passing a new config. Check out: npmjs.com/package/xml2js -The module also always returns an array so you need to do resultvalue[0].$.name
Thanks a tone :) @Bergur.
0

this is a simpler way to access testsuite name with camaro

const { transform } = require('camaro')

async function main() {
    const xml = `
    <?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="QA" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="QA2" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="UAT" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="UAT2" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="SandBox" ></testsuite>
<testcase status="success>"></testcase>
<testsuite name="SandBox" ></testsuite>
</testsuites>
`

    template = {
        names: ['testsuites/testsuite', '@name']
    }
    const { names } = await transform(xml, template)
    console.log(names);
}

main()

output

[ 'QA', 'QA2', 'UAT', 'UAT2', 'SandBox', 'SandBox' ]

Comments

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.