Skip to content

Fix unbound prefix recovery when xmlns:dlna is absent#52

Closed
dfortis wants to merge 2 commits into
StevenLooman:masterfrom
dfortis:fix/unbound-prefix-without-dlna-namespace
Closed

Fix unbound prefix recovery when xmlns:dlna is absent#52
dfortis wants to merge 2 commits into
StevenLooman:masterfrom
dfortis:fix/unbound-prefix-without-dlna-namespace

Conversation

@dfortis

@dfortis dfortis commented Jun 21, 2026

Copy link
Copy Markdown

Summary

The strict=False recovery added in #35 anchored its namespace injection on an existing xmlns:dlna declaration. Some real-world devices (JBL Authentics, WiiM/LinkPlay) emit <song:*> tags without declaring xmlns:dlna, so the injection was silently skipped and the unbound prefix remained, raising ParseError when the path was otherwise supposed to recover.

This regression is observable today: python-didl-lite==1.5.0 is shipped via async-upnp-client into Music Assistant, where JBL Authentics 200 owners still see ~100 unbound prefix errors per hour and a broken DLNA state-sync loop (downstream tracking: music-assistant/support#4398).

Fix

Anchor the namespace injection on the DIDL-Lite root opening tag (`<DIDL-Lite`) instead of the optional `xmlns:dlna` declaration. The root element is guaranteed to be present in any valid DIDL-Lite document, so recovery works regardless of which namespace declarations the producer chose to include.

Also batches all missing prefix injections into a single regex substitution rather than looping per-prefix.

Test

Added `test_from_xml_string_unbound_prefix_without_dlna_namespace` that exercises the no-`xmlns:dlna` case. The existing `test_from_xml_string_unbound_prefix` (with `xmlns:dlna` present) still passes — the new injection is anchored on the root tag which is also present in that case.

```
$ python3 -m pytest tests/ -v
...
26 passed in 0.18s
```

`ruff check` clean.

Compatibility

  • No behavior change when `strict=True` (recovery code path is gated by `if not strict`).
  • No behavior change for XML that did contain `xmlns:dlna` and had unbound prefixes (Handle unbound XML prefixes when strict=False #35 case continues to work).
  • Recovers an additional class of input that previously raised.

sfortis and others added 2 commits June 21, 2026 13:37
The strict=False recovery added in StevenLooman#35 anchored its namespace injection
on an existing `xmlns:dlna` declaration. Some real-world devices (JBL
Authentics, WiiM/LinkPlay) emit `<song:*>` tags without declaring
`xmlns:dlna`, so the injection was silently skipped and the unbound
prefix remained, raising ParseError when otherwise recoverable.

Anchor the injection on the DIDL-Lite root opening tag instead. That
element is guaranteed to be present in any valid DIDL-Lite document, so
the recovery works regardless of which namespace declarations the
producer chose to include.

Also batch all missing prefixes into a single regex substitution and add
a regression test that exercises the no-dlna-namespace case.
@dfortis

dfortis commented Jun 21, 2026

Copy link
Copy Markdown
Author

Closing — opened from wrong GitHub account. Will reopen the identical change from my personal account shortly.

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