NaturalIntelligence / fast-xml-parser

Validate XML, Parse XML and Build XML rapidly without C/C++ based libraries and no callback.
https://naturalintelligence.github.io/fast-xml-parser/
MIT License
2.56k stars 306 forks source link

IsArray option isn't parsing tags with 0 as value correctly #490

Closed DolarJoe closed 1 year ago

DolarJoe commented 2 years ago

Description

I'd like to use IsArray option, however, it seems to break on tags which have value 0 inside of them, such as 0 or 0.0. It is inconsistent with other numbers, interger or floats, that have non 0 value, as shown in my provided example.

Input

<root>
    <a>0.00</a>
    <b>0.01</b>
</root>

Code

const parser = new XMLParser({isArray: (name, jpath, isLeaf, isAttr) => !isLeaf});
let result = parser.parse(fr.result);
console.log(JSON.stringify(result, undefined, 2))

Output

{
  "root": [
    {
      "a": [
        0
      ],
      "b": 0.01
    }
  ]
}

expected data

{
  "root": [
    {
      "a": 0,
      "b": 0.01
    }
  ]
}

Would you like to work on this issue?

github-actions[bot] commented 2 years ago

I'm glad you find this repository helpful. I'll try to address your issue ASAP. You can watch the repo for new changes or star it.

omggga commented 1 year ago

Yes, the same issue for me.

There is a function for it in code:

function isLeafTag(obj, options){
  const propCount = Object.keys(obj).length;
  if( propCount === 0 || (propCount === 1 && obj[options.textNodeName]) return true;
  return false;
}

https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/src/xmlparser/node2json.js#L98

The problem is that obj[options.textNodeName] is checking the value exist, but if it false or 0 it will fail the test. So you can try to fix it to test it also for boolean type or zero.

You can check it with this xml:

<root>
    <a>0</a>
    <b>false</b>
</root>

and this option:

const isArray = function(name, jpath, isLeafNode, isAttribute){ 
    if (!isLeafNode) return true
}

I see for now only one way to fix it:

if( propCount === 0 || (propCount === 1 && (obj[options.textNodeName] || typeof obj[options.textNodeName] === "boolean" || obj[options.textNodeName] === 0))) return true;
amitguptagwl commented 1 year ago

fixed as part of 4.1.4