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

isArray empty array produces an array with a single string #549

Open chriscarpenter12 opened 1 year ago

chriscarpenter12 commented 1 year ago

Description

When using the isArray to specify which tags should be an array. If the tag is empty it produces an output with an array of a single empty string. [""] instead of the expected [].

Input

<root>
    <EventList></EventList>
</root>

Code

new XMLParser({
    ignoreAttributes: true,
    isArray: (name) => {
      return name.endsWith('List');
    },
  });
trimValues: true,
parseTagValue: true,

These don't seem to have any change on output in this scenario either.

Output

{
  "EventList": [
    ""
  ],
}

expected data

{
  "EventList": [],
}

Would you like to work on this issue?

github-actions[bot] commented 1 year 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.

amitguptagwl commented 1 year ago

Consider this,

<root>
    <EventList>a</EventList>
    <EventList>b</EventList>
</root>

The expected output should be

{
  root: {
     EventList: ['a', 'b']
  }
}

Similarly for empty entries

{
  root: {
     EventList: ['', '']
  }
}

And for one entry

{
  root: {
     EventList: ['']
  }
}
chriscarpenter12 commented 1 year ago

I guess I should have been more clear or that maybe I misunderstood what isArray is doing. I thought by saying EventList is an array would treat any items below it as objects or items. What my object more closely looks like is:

<root>
    <EventList>
      <Event>
        <ID>1</ID>
        <Name>Something</Name>
      </Event>
      <Event>
        <ID>2</ID>
        <Name>Something Else</Name>
      </Event>
    </EventList>
</root>

Output

{
  EventList: [
    { 
      Event: {
        ID: 1,
        Name: "Something"
      }
    },
    { 
      Event: {
        ID: 2,
        Name: "Something Else"
      }
    }
  ],
}

So when EventList was declared an array with nothing inside the empty string surprised me. In my case there's times where there's no events. Is setting isArray on EventList wrong?

amitguptagwl commented 1 year ago

What actually you're looking for is that and empty content of a tag should not be considered as array item. I don't think any current options can help you.

chriscarpenter12 commented 1 year ago

I’ll leave it as is then and continue post processing the object with a sanitize function after xml parsing. I was just hoping to avoid walking the whole object as some responses are quite large

chriscarpenter12 commented 1 year ago

For others that may have a similar question. I looked at the output more carefully and the array is by default on the item key name not the parent like what I originally expected so in my example I changed it to

new XMLParser({
    ignoreAttributes: false,
    processEntities: false,
    trimValues: true,
    parseTagValue: true,
    isArray: (name, jPath) => {
      return jPath.endsWith(`List.${name}`);
    },
  });

And in my post processing I had to change any parent tags ending with List to be an object instead of an empty string because that's how the parser treated them as tagValueProcessor would not iterate over empty values.

amitguptagwl commented 1 year ago

What do u think about a feature where your sample XML can be transformed to this

{
  EventList: [
    { 
        ID: 1,
        Name: "Something"
    },
    { 
        ID: 2,
        Name: "Something Else"
    }
  ],
}
chriscarpenter12 commented 1 year ago

I think that’s what I initially wanted but if you try to use the builder to do js -> xml it wouldn’t know that the list array items are an Event. That’s why I modified what did because I need to convert back to xml too.

Although what would be nice if defining an array the parent would always be an object not an empty string if the array has no items. I still have to post process the js output to fix that.

amitguptagwl commented 1 year ago

We'll have to think different possibilities and usage but let me reopen the bug so that whenever I get time, I can think about

amitguptagwl commented 1 year ago

What's about to introduce an option skipEmptyListItem: true?