Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attributes are not included in simple result for elements without children #19

Closed
dasDaniel opened this issue Nov 21, 2020 · 3 comments
Closed

Comments

@dasDaniel
Copy link
Contributor

dasDaniel commented Nov 21, 2020

Wasn't sure whether this was a feature or bug, but I'm thinking it might be the latter.

Here is the input

<response>
  <error msg="haha, nice try">
    <anything></anything>
  </error>
</response>

and this is the output

{
  "response": {
    "error": {
      "anything": "",
      "_attributes": {
        "msg": "haha, nice try"
      }
    },
    "_attributes": {}
  }
}

if I take out the anything tags, the msg attribute is not included anymore

<response>
  <error msg="haha, nice try">
  </error>
</response>

result:

{
  "response": {
    "error": "",
    "_attributes": {}
  }
}

but I'm expecting:

{
  "response": {
    "error": {
      "_attributes": {
        "msg": "haha, nice try"
      }
    },
    "_attributes": {}
  }
}

It looks like the presence of an additional child tag is required to treat the element as an object instead of as a string value

@TobiasNickel
Copy link
Owner

yes, I would also expect that. I will look into this later this weekend.

@TobiasNickel
Copy link
Owner

Actually it is a feature, But this is a situation where some decision need to be made, and there will always be situations that some developers would expect the opposite (not the fault of the developer).
For the implementation of txml.simplify I have made the same output as PHP simpleXML.

To get the result you expected, you can use the following method it return what is expected, but other developers would think "why is errors now an object and not a string".

function logicalSimplify(children) {
    var out = {};

    if (children.length === 1 && typeof children[0] == 'string') {
        return children[0];
    }
    // map each object
    children.forEach(function(child) {
        if (typeof child !== 'object') {
            return;
        }
        if (!out[child.tagName])
            out[child.tagName] = [];
        var kids = logicalSimplify(child.children);
        out[child.tagName].push(kids);
        if (Object.keys(child.attributes).length) {
            kids._attributes = child.attributes;
        }
    });

    for (var i in out) {
        if (out[i].length == 1) {
            out[i] = out[i][0];
        }
    }

    return out;
};

To resolve that issue, I made the txml.simplifyLostLess() implementation. It might not be as pretty, because every value is going to be an array, even if it has only one item. But when there are situations, where there can be one or more items of the same type, then it need to stay an array. As developer then there is the direct way, to know there is only one and access the value using ...[0] or as an array using ....map(...) or forEach.

@dasDaniel
Copy link
Contributor Author

That's the problem with xml=>json, it's hard to tell intent. The nice thing is that using the xml method, the user can reduce as needed to get desired result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants