Skip to content

Capture unknown elements into one extension tree - #334

Open
mmcdole wants to merge 2 commits into
masterfrom
feat/276-custom-element-tree
Open

Capture unknown elements into one extension tree#334
mmcdole wants to merge 2 commits into
masterfrom
feat/276-custom-element-tree

Conversation

@mmcdole

@mmcdole mmcdole commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Fixes #276. Fixes #203. Fixes #82.

Unknown elements were handled three inconsistent ways: namespaced elements became the recursive ext.Extension tree, non-namespaced item children went into the flat Item.Custom map (dropping nesting, attributes and repetition, which is #203's corruption and #82's missing data), and unknown elements at channel level, atom feed, entry and source level were skipped and lost entirely.

This lands the #276 plan in its v1-additive form:

  • shared.ParseCustom parses any unrecognized non-namespaced element with the same recursive builder namespaced extensions already use, and files it under the _custom pseudo namespace, preserving nesting, attributes and repetition. After Route the parser element loops through one shared helper #333 the capture point was one default: case per container, so the wiring is one line each in the rss channel/item and atom feed/entry/source parsers. The RSS 1.0 <items> rdf:Seq stays skipped: it is a structural list of item references, not content.
  • Item.Custom stays as a compatibility shim fed from the tree. Childless elements keep their flat value exactly as before (entity-decoded, last one wins); nested elements no longer produce corrupted flat text, they live fully formed in the tree. The field is documented as deprecated in favor of the tree; removal waits for v2.
  • Feed and Item gain GetExtension, GetExtensionValue and GetCustomValue accessors (the ergonomic layer from the old v2-custom-elements branch, adapted). That branch's parser approach was not used: it captured customs with flat ParseText, so it relocated the corrupted / mangled nested custom XML #203 corruption rather than fixing it.

Behavior notes: everything here is additive. Four existing fixtures gain extensions._custom blocks (82 added lines, zero removed or changed values, custom maps byte-identical). Data that was previously discarded (channel-level and atom-level unknowns) now appears in Extensions; feeds without unknown elements produce identical output.

Tests: nine new fixture pairs (channel-level customs, attributes, repetition, CDATA, nesting, custom-plus-extension mixes, atom feed and entry customs, and a nested-with-CDATA case reproducing #203) plus an accessor unit test covering namespaced lookups, feed and item custom values, repetition, nested children, the shim's childless-only contract, and absent-key behavior.

Unknown elements were handled three inconsistent ways: namespaced ones
became the ext.Extension tree, non-namespaced item children went into
the flat Item.Custom map (dropping nesting, attributes and repetition),
and unknown elements at channel, atom feed, entry and source level were
skipped and lost.

shared.ParseCustom now parses any unrecognized non-namespaced element
with the same recursive builder namespaced extensions use and files it
under the _custom pseudo namespace. The rss channel and item parsers
and the atom feed, entry and source parsers capture through it; the
RSS 1.0 <items> rdf:Seq stays skipped since it is a structural list of
references, not content.

Item.Custom is kept as a compatibility shim fed from the tree: childless
elements keep their flat value (entity-decoded as before, last wins),
and nested elements no longer corrupt it, they live fully formed in the
tree instead. Feed and Item gain GetExtension, GetExtensionValue and
GetCustomValue accessors.

Existing fixture output changes are purely additive: 82 added lines of
extensions across four fixtures, no removed or altered values. New
fixtures cover channel level customs, attributes, repetition, CDATA,
nesting, custom-plus-extension mixes, and atom feed and entry customs.

Fixes #276
Fixes #203
Fixes #82
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.31373% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.82%. Comparing base (16bfe36) to head (4103507).

Files with missing lines Patch % Lines
extension_helpers.go 83.33% 3 Missing and 1 partial ⚠️
internal/shared/extparser.go 75.00% 1 Missing and 1 partial ⚠️
rss/parser.go 87.50% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #334      +/-   ##
==========================================
+ Coverage   79.75%   79.82%   +0.06%     
==========================================
  Files          22       23       +1     
  Lines        1912     1948      +36     
==========================================
+ Hits         1525     1555      +30     
- Misses        298      302       +4     
- Partials       89       91       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Unify custom + extension elements into one arbitrary-element tree corrupted / mangled nested custom XML Parsing custom tags in Item

1 participant