CoreOffice / XMLCoder

Easy XML parsing using Codable protocols in Swift
https://coreoffice.github.io/XMLCoder/
MIT License
801 stars 112 forks source link

XmlEncoder: ordering of elements #17

Closed Ma-He closed 5 years ago

Ma-He commented 5 years ago

Hi, is there any possibility to set the order of attributes in an element while encoding a model-instance? I'm trying to build a GPX reader/writer with this little awesome framework and have noticed that the order of my attributes in an element varies from encode to encode. Am I missing something?

Thanks in advance

MaxDesiatov commented 5 years ago

Hi @Ma-He, thank you reporting this issue. There's a .sortedKeys option that can be set for XMLEncoder.outputFormatting property.

We plan to publish auto-generated docs for XMLCoder soon, which would make this option more visible to users.

Also, if you're using this option, you might need to switch to master branch as it was recently reported that this option was broken. This was fixed in #11 and #14 and merged to master.

regexident commented 5 years ago

Sorting is not was OP is looking for. Ordering is. That is <foo>…</foo> has to appear before <bar>…</bar>, if .foo was encoded before .bar.

This is not supported currently as XMLCoder uses unordered NSDictionary in its internal keyed encoding container.

MaxDesiatov commented 5 years ago

Thanks @regexident, I understand now. Still, my understanding was that the main concern is about determinism. I hope that .sortedKeys is able to solve that. I guess we have to transition to a tuple array for internal storage to maintain order as well.

regexident commented 5 years ago

I'm fairly certain as writing a Codable-powered GPX implementation was my reason for dabbling with XMLCoder (or rather it's predecessor XMLParser) as well.

GPX (like many other XML schemas) expects certain keys to have a specific order:

Search for <!-- elements must appear in this order --> in the GPX 1.1 Schema.

This requirement of specific order also applies to elements, not just attributes.

Ma-He commented 5 years ago

Hey guys,

thanks for your quick responses. As @regexident said, ordering it is what I`m looking for :-)

regexident commented 5 years ago

Nitpick: It's not the order of attributes that's unsupported, it's the order of elements.

The XML specification explicitly defines the order of attributes to be of no importance:

The Name in the start- and end-tags gives the element's type. [Definition: The Name-AttValue pairs are referred to as the attribute specifications of the element], [Definition: with the Name in each pair referred to as the attribute name ] and [Definition: the content of the AttValue (the text between the ' or " delimiters) as the attribute value.] Note that the order of attribute specifications in a start-tag or empty-element tag is not significant. (emphasis mine) Source

As such NSXMLParser (which XMLCoder is based on) doesn't even provide a way to retrieve an element's attributes in the order of appearance.

MaxDesiatov commented 5 years ago

TLDR: We're slowly working towards ordered child elements, but not quite sure if ordering of attribues will be possible in the current implementation.

@Ma-He could you please clarify if you're looking for ordering of XML attributes or child elements?

MaxDesiatov commented 5 years ago

If you're specifically interested in supporting GPX, looks like it only requires ordered elements, not attributes.

Ma-He commented 5 years ago

@MaxDesiatov you`re right, just the elements

CineDev commented 5 years ago

I have to say you doing great job! But current iteration of XMLEncoder is basically broken for use cases where the ordering is important. I tried to use it in my simple text editor. I'm storing each paragraph individually in my model. But from save to save my model xml representation gets shuffled, so the text information in the saved document become completely useless. I hope, the ordering is on the way.

MaxDesiatov commented 5 years ago

@Ma-He @CineDev this is now fixed in master, no source-breaking API changes, should work out of the box. .sortedKeys now only has effect on attributes, not attributes and elements like before.