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.52k stars 303 forks source link

Suggestion: Choose how empty nodes are handled. #683

Open Alynntheyelloweyed opened 1 week ago

Alynntheyelloweyed commented 1 week ago

Description

No options set in parser or output builder converts an empty xml node into an empty object. In order to not rewrite my entire project I need the json output for fast-xml-parser to match the output of the module currently in use. Even using v5 did not give me the output desired. I've had to give up utilizing this module.

Input

I've tried every combination of option settings for v5, both parser and object builder and none of them produce the results I want. Based on other threads this should be added in v5. But no option set in either the Parser or Builder does this.

Code

I've tried multiple different options, this one gets me close to my intended output, but not what I expect/want.

import XMLParser from "fast-xml-parser/src/v5/XMLParser.js";
import JsObjOutputBuilder from "fast-xml-parser/src/v5/OutputBuilders/JsObjBuilder.js"

const builder = new JsObjOutputBuilder(
    {
        attributes: {
            prefix: ''
        },
        nameFor:{
            text: '$t'
        },
    }
)

const parser = new XMLParser (
    {
        OutputBuilder: builder,
    }

);

Output

"effects": {"/": true},

expected data

"effects": {},

In my experimentation I found that onAttribute nearly gets me there but it is flawed.

const builder = new JsObjOutputBuilder({
    attributes: {
        prefix: '',
        entities: true,
    },
    nameFor:{
        text: '$t'
    },
    onAttribute: (name, value, tagname) => { 
        if (name == '/') {
            name = '';
            value='';
            //return ''; this was another test
        }
        return {name, value, tagname};
    },
});

making the name and value empty strings gives you effects:{:''}. Return any value by itself gives you effects:{undefined:undefined} while in memory, after you stringify it however, you get {} as expected.

Suggestion create an onEmptyNode or something to that effect that can be set to 'Object', 'Array', 'String', 'Boolean'

If set to Object it returns {} for empty nodes, If set to Array it returns [] for empty nodes. If String it returns "" for empty nodes (current default behavior for 4), or {$text: ""} if alwaysCreateTextNode is set. If Boolean it returns {"/": true} for empty nodes (current default behavior for v5 JsObjOutputBuilder)

These four look to be covering all the use cases for the other requests I've read here, as well as the two current default behaviors for JsObjectOutputBuilder

I really like this library overall, and it is anywhere between 10 to 35% faster than my current one. But as I can't get empty object output on empty tags it isn't worth switching my entire application's code over to deal with it.

Would you like to work on this issue?

amitguptagwl commented 6 days ago

the development of v5 was not completed. so it was deleted as experimental. However, are you looking for empty attribute or tag? updateTag with v4 can be used to set empty attributes. I'll have to check what I did for v5.

Alynntheyelloweyed commented 6 days ago

What I need is the following.

the xml

<tagname /> or 
<tagname></tagname> 

to be parsed to

"effects": {}

What I suggested was to give us a option setting to decide if we want empty nodes to be treated as an empty object (my case) an empty array, an empty string value (the v4 way), or "/": true as it is in V5. Heck, you could even give another option to skip it altogether.

amitguptagwl commented 5 days ago

this is not supported in v4 and current implementation doesn't allow to implement this. I targeted for v5. I would be checking and suggest an example if it is covered.

Alynntheyelloweyed commented 5 days ago

I've already tried, and as I explained v5 implementation also does not allow for it, hence the suggestion to add it. You can get close, but you cannot actually get there.