Skip to content

Separates XML attribute and child element lookup - #72

Closed
NickSdot wants to merge 2 commits into
php-soap:mainfrom
NickSdot:bug/xml-attribute-element-collisions
Closed

NickSdot wants to merge 2 commits into
php-soap:mainfrom
NickSdot:bug/xml-attribute-element-collisions

Conversation

@NickSdot

Copy link
Copy Markdown
Contributor
Q A
Type bug
BC Break no
Fixed issues -

Summary

Hey! Prevenst XML attributes from overwriting or being mistaken for child elements. Resolves schema attributes by namespace while preserving non conflicting legacy lookup keys for custom decoder lenses. Regression tests for collisions, absent children, qualified and unqualified attributes, repeated children and simple text content.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c81aee97-d84b-4d56-a9ac-a83b313a5265
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@veewee

veewee commented Oct 15, 2026

Copy link
Copy Markdown
Member

@NickSdot, you caught a nasty one here. Attributes and child elements ended up in one array keyed by local name, so xsi:type or any other attribute could overwrite a child with the same name, or show up as a child that was not there. Your test cases cover every variant of it, which made the rebuild a lot easier.

The decode side changed underneath this PR in the meantime, so I rebuilt it in #80. Your tests are ported there, and you are co-author on the commits that carry them.

I went with a different shape than the @{namespace}name keys. Decoding now reads from a small ElementLookup object that keeps child elements and attributes apart and looks attributes up by namespace. Custom decoder lenses get that object as well, so they can ask for an attribute in its namespace directly. After that nothing read the flat array anymore, so DocumentToLookupArrayReader is gone, and the two tests that asserted the @{...} keys now assert attribute() instead.

While testing namespaces I also ran into attributes declared through ref, like xml:lang, which were read and written without their namespace. A wsdl-reader change now marks those as qualified, so they come out right in both directions.

Thanks for pushing this. I'm closing this one in favour of #80, so the discussion continues there.

@veewee veewee closed this Oct 15, 2026
@NickSdot
NickSdot deleted the bug/xml-attribute-element-collisions branch October 15, 2026 16:15
veewee added a commit to veewee/encoding that referenced this pull request Oct 16, 2026
…ildren

DocumentToLookupArrayReader puts child elements and attributes in one flat array keyed by local name, so an attribute overwrites or stands in for a child with the same name, xsi:type and xmlns declarations included. ElementLookup keeps them apart: element() only returns child elements, attribute() reads by namespace and local name, text() follows the existing '_' rule, and toArray() builds the legacy array with the child winning on a collision and protocol attributes left out.

attribute() falls back to the only other attribute with that local name when the exact namespace is absent. That keeps xml:lang, other ref attributes and servers that qualify attributes differently from their WSDL decoding, while id next to a:id still resolves to the right one.

The child wins rule, the protocol attribute filter and two of the tests come from php-soap#72. Nothing uses it yet.

Co-authored-by: NickSdot <catch.github.com.nicksdot@nicksdot.dev>
veewee added a commit to veewee/encoding that referenced this pull request Oct 16, 2026
The built-in decoder lenses read child elements, attributes and the '_' text from ElementLookup instead of the flat lookup array. An attribute no longer overwrites or stands in for a child element with the same name, xsi:type and namespace declarations included, and an attribute property only reads the attribute in its own namespace, with the single namesake fallback of ElementLookup::attribute().

ObjectEncoder::from builds one lookup per element. DocumentToLookupArrayReader now returns ElementLookup::toArray(), so its callers get the same fix: the child wins on a collision and xsi, soap-enc and xmlns attributes are left out.

Custom decoder lenses still receive that array through an adapter that ObjectAccess builds once per property. The next commit hands them the lookup itself. Because the adapter is the innermost frame in src/ now, the allowed throw of the throwing lens fixture moves from ObjectEncoder to ObjectAccess.

The tests port php-soap#72. Its two lookup array tests are in ElementLookupTest since the previous commit, asserting attribute() where php-soap#72 asserted '@{ns}name' keys, which this design does not have.

Co-authored-by: NickSdot <catch.github.com.nicksdot@nicksdot.dev>
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

Successfully merging this pull request may close these issues.

2 participants