Skip to content

Non-deterministic root attribute ordering during XML encoding #297

@JoshBashed

Description

@JoshBashed

Summary

XMLCoder currently does not guarantee deterministic ordering of root XML attributes during encoding. This makes encoded XML output unstable across runs and complicates snapshot testing or byte-for-byte comparisons.

Note

This issue was generated using AI tooling.

Problem

When doing encoding tests for XML, I need to disable inclusion of rootAttributes for testing because their ordering is not deterministic.

For example, the same encoded object may produce different attribute ordering between runs:

<Package xmlns="..." xmlns:uap="..." IgnorableNamespaces="uap" />

and:

<Package IgnorableNamespaces="uap" xmlns:uap="..." xmlns="..." />

Even though these are semantically equivalent XML documents, the resulting byte output differs, which causes snapshot or equality-based tests to fail.

Currently, I need to use a workaround similar to:

static func encodeXMLData(
  _ manifest: XMLData,
  disablingRootAttributesForTesting: Bool = false
)

Expected Behavior

Encoded XML attribute ordering should be deterministic across runs.

Possible solutions could include:

  • Preserving insertion order
  • Sorting attributes before serialization
  • Providing a configurable ordering strategy

Impact

This affects:

  • Snapshot testing
  • Byte-for-byte output comparisons
  • Reproducible build workflows
  • Stable XML fixture generation

It also forces downstream consumers to omit root attributes during tests, reducing test coverage of the final encoded XML output.

Additional Context

I understand XML attribute order is not semantically meaningful according to the XML specification. However, deterministic output is still important for testing and reproducibility purposes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions