home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
70.06k stars 29.13k forks source link

XML not well-formed exception if special charaters are present in artist or title #121369

Open LosLockos13 opened 2 weeks ago

LosLockos13 commented 2 weeks ago

The problem

Dear maintainers, I'm struggling on the following problem since a while and I hope I do it right asking for help that way.

I'm playing songs from Gerbera (which by the way is as well a very nice implementation which I love to use the same as Home Assistant). In some cases the status of my DLNA renderer (Onkyo Receiver) is not getting updated anymore and the log gets filled with xml parse errors. I figured out that is only happens if special characters like "&" are present in artist or title and started debugging as far as my limited knowledge allowed.

I guess that I was able to figure out the root cause of this. When calling GetPositionInfoResponse the receiver seems to escape an "&" in artist and title correctly using "&". Then I see GetPositionInfo from async_upnp_client is delivering response_args where "&" in the fields like title, creator or artist is not escaped and this seems to cause the followed exception in async_update media_player.

I would appreciate any help on this very much. Than you and best regards, LosLockos

PS: I might have found a comparable topic here. But this is just a guess: https://github.com/StevenLooman/async_upnp_client/issues/50

What version of Home Assistant Core has the issue?

core-2024.7.1

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Core

Integration causing the issue

dlna_dmr

Link to integration documentation on our website

https://www.home-assistant.io/integrations/dlna_dmr/

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

2024-07-06 10:06:24.323 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Got response from POST http://192.168.20.180:8888/Control/oap/AVTransport:
200
Date: Sat, 06 Jul 2024 08:06:24 GMT
Content-Type: text/xml; charset="utf-8"
Content-Encoding: gzip
Ext: 
Server: Linux/4.9.123 UPnP/1.0 GUPnP/0.20.13
Content-Length: 697

b'<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetPositionInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:2"><Track>1</Track><TrackDuration>0:03:41</TrackDuration><TrackMetaData>&lt;DIDL-Lite xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot;&gt;&lt;item id=&quot;1720250272820&quot; parentID=&quot;0&quot; restricted=&quot;0&quot;&gt;&lt;upnp:class&gt;object.item.audioItem.musicTrack&lt;/upnp:class&gt;&lt;dc:title&gt;Well Balanced&lt;/dc:title&gt;&lt;dc:creator&gt;Oliver Shanti &amp; Friends&lt;/dc:creator&gt;&lt;upnp:album&gt;10 Years Sattva Music&lt;/upnp:album&gt;&lt;upnp:artist&gt;Oliver Shanti &amp; Friends&lt;/upnp:artist&gt;&lt;upnp:albumArtURI&gt;http://192.168.20.101:49153/content/media/object_id/14/res_id/1/ext/file.jpg&lt;/upnp:albumArtURI&gt;&lt;res protocolInfo=&quot;http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000&quot; duration=&quot;00:03:41&quot; size=&quot;7266015&quot;&gt;http://192.168.20.101:49153/content/media/object_id/14/res_id/0/group/default/ext/file.mp3&lt;/res&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData><TrackURI>http://192.168.20.101:49153/content/media/object_id/14/res_id/0/group/default/ext/file.mp3</TrackURI><RelTime>0:00:01</RelTime><AbsTime>0:00:01</AbsTime><RelCount>0</RelCount><AbsCount>0</AbsCount></u:GetPositionInfoResponse></s:Body></s:Envelope>'
2024-07-06 10:06:24.326 DEBUG (MainThread) [async_upnp_client.client] Called action: GetPositionInfo, args: {'InstanceID': 0}, response_args: {'Track': 1, 'TrackDuration': '0:03:41', 'TrackMetaData': '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="1720250272820" parentID="0" restricted="0"><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:title>Well Balanced</dc:title><dc:creator>Oliver Shanti & Friends</dc:creator><upnp:album>10 Years Sattva Music</upnp:album><upnp:artist>Oliver Shanti & Friends</upnp:artist><upnp:albumArtURI>http://192.168.20.101:49153/content/media/object_id/14/res_id/1/ext/file.jpg</upnp:albumArtURI><res protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000" duration="00:03:41" size="7266015">http://192.168.20.101:49153/content/media/object_id/14/res_id/0/group/default/ext/file.mp3</res></item></DIDL-Lite>', 'TrackURI': 'http://192.168.20.101:49153/content/media/object_id/14/res_id/0/group/default/ext/file.mp3', 'RelTime': '0:00:01', 'AbsTime': '0:00:01', 'RelCount': 0, 'AbsCount': 0}
2024-07-06 10:06:24.332 ERROR (MainThread) [homeassistant.helpers.entity] Update for media_player.tx_nr696_dlna fails
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1701, in feed
    self.parser.Parse(data, False)
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 332

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 944, in async_update_ha_state
    await self.async_device_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1296, in async_device_update
    await self.async_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 498, in async_update
    await self._device.async_update(do_ping=do_ping)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 360, in async_update
    await self._async_poll_state_variables(
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/profile.py", line 468, in _async_poll_state_variables
    self._on_event(service, changed_state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 400, in _on_event
    self.on_event(service, state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 533, in _on_event
    self.async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 358, in async_write_ha_state
    super().async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1007, in async_write_ha_state
    self._async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1133, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1091, in __async_calculate_state
    if (entity_picture := self.entity_picture) is not None:
                          ^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1068, in entity_picture
    return self.media_image_local
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1073, in media_image_local
    if (image_hash := self.media_image_hash) is None:
                      ^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 639, in media_image_hash
    if (url := self.media_image_url) is not None:
               ^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 894, in media_image_url
    return self._device.media_image_url
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 1198, in media_image_url
    items = _cached_from_xml_string(xml)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 239, in _cached_from_xml_string
    return didl_lite.from_xml_string(xml, strict=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/didl_lite/didl_lite.py", line 1077, in from_xml_string
    xml_el = defusedxml.ElementTree.fromstring(xml_string)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/defusedxml/common.py", line 126, in fromstring
    parser.feed(text)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1703, in feed
    self._raiseerror(v)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1610, in _raiseerror
    raise err
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 332

Additional information

No response

home-assistant[bot] commented 2 weeks ago

Hey there @chishm, mind taking a look at this issue as it has been labeled with an integration (dlna_dmr) you are listed as a code owner for? Thanks!

Code owner commands Code owners of `dlna_dmr` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Renames the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign dlna_dmr` Removes the current integration label and assignees on the issue, add the integration domain after the command. - `@home-assistant add-label needs-more-information` Add a label (needs-more-information, problem in dependency, problem in custom component) to the issue. - `@home-assistant remove-label needs-more-information` Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


dlna_dmr documentation dlna_dmr source (message by IssueLinks)

chishm commented 2 weeks ago

Hi, and thank you for the bug report. You're right in that the issue is the & in the track metadata is not escaped correctly, but in this case I think it's the fault of the receiver. I extracted the TrackMetaData node from the raw XML you posted above, to get:

<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="1720250272820" parentID="0" restricted="0"><upnp:class>object.item.audioItem.musicTrack</upnp:class><dc:title>Well Balanced</dc:title><dc:creator>Oliver Shanti & Friends</dc:creator><upnp:album>10 Years Sattva Music</upnp:album><upnp:artist>Oliver Shanti & Friends</upnp:artist><upnp:albumArtURI>http://192.168.20.101:49153/content/media/object_id/14/res_id/1/ext/file.jpg</upnp:albumArtURI><res protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000" duration="00:03:41" size="7266015">http://192.168.20.101:49153/content/media/object_id/14/res_id/0/group/default/ext/file.mp3</res></item></DIDL-Lite>

This should also be valid XML, but it's not, because the & in Oliver Shanti & Friends should in fact be Oliver Shanti &amp; Friends. The XML needs to be doubly-escaped so in the raw XML it would look like Oliver Shanti &amp;amp; Friends. To be honest, the UPnP & DLNA specifications are overly complicated and I'm not surprised device manufacturers get this wrong.

One question to check, was this track started by Home Assistant (say, by browsing media then playing it), or was it started directly through the Receiver? If the former, then maybe there's a bug in the dlna_dmr component in setting the track metadata. If the latter, then I'd say it's a problem with the Receiver (wouldn't be the first one) and I'll have to look into adding a quirk to async-upnp-client to deal with it (it's not the first device to not escape & correctly).

LosLockos13 commented 2 weeks ago

Hi, thank you very much for going into that. While reviewing the issues of the past I already realized that the usual cause for DLNA issues are on the renderer side and that the specification is that kind of complex that one only hardly do it the right way. It really looks like the only way to handle it is to adapt to all the "variants" that are out there.

To answer your question: I've played the track for Gerbera directly (using an Andrid app). While investigating further I realized that I've another DLNA capable renderer (LG TV) that I never used and I feed the same tite the same way to this one and grabbed the same call. And, indeed the received xml is double escated and everything went well:

2024-07-07 07:59:18.298 DEBUG (MainThread) [async_upnp_client.client] Calling action: GetPositionInfo, args: {'InstanceID': 0}
2024-07-07 07:59:18.299 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Sending request:
POST http://192.168.20.115:1951/AVTransport/04645007-7a4d-50fe-ef88-9e76dc1c7347/control.xml
SOAPAction: "urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"
Host: 192.168.20.115:1951
Content-Type: text/xml; charset="utf-8"
<?xml version="1.0"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:GetPositionInfo></s:Body></s:Envelope>

2024-07-07 07:59:18.319 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Got response from POST http://192.168.20.115:1951/AVTransport/04645007-7a4d-50fe-ef88-9e76dc1c7347/control.xml:
200
DLNADeviceName.lge.com: LGTV
Ext: 
Date: Sun, 07 Jul 2024 05:59:17 GMT
Server: Linux/i686 UPnP/1,0 DLNADOC/1.50 LGE WebOS TV/Version 0.9
Content-Length: 1839
Content-Type: text/xml; charset="utf-8"
Connection: close

b'<?xml version="1.0" encoding="UTF-8"?>\r\n<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:GetPositionInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><Track>1</Track><TrackDuration>00:03:41</TrackDuration><TrackMetaData>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/"&gt;&lt;item id="1720331262943" parentID="0" restricted="0"&gt;&lt;dc:title&gt;Well Balanced&lt;/dc:title&gt;&lt;dc:creator&gt;Oliver Shanti &amp;amp; Friends&lt;/dc:creator&gt;&lt;upnp:artist&gt;Oliver Shanti &amp;amp; Friends&lt;/upnp:artist&gt;&lt;upnp:actor&gt;Oliver Shanti &amp;amp; Friends&lt;/upnp:actor&gt;&lt;upnp:author&gt;Oliver Shanti &amp;amp; Friends&lt;/upnp:author&gt;&lt;upnp:album&gt;10 Years Sattva Music&lt;/upnp:album&gt;&lt;upnp:genre&gt;Unknown&lt;/upnp:genre&gt;&lt;upnp:albumArtURI&gt;http://192.168.20.101:49153/content/media/object_id/24/res_id/1/ext/file.jpg&lt;/upnp:albumArtURI&gt;&lt;res duration="0:03:41" size="7266015" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"&gt;http://192.168.20.101:49153/content/media/object_id/24/res_id/0/group/default/ext/file.mp3&lt;/res&gt;&lt;upnp:class&gt;object.item.audioItem.musicTrack&lt;/upnp:class&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData><TrackURI>http://192.168.20.101:49153/content/media/object_id/24/res_id/0/group/default/ext/file.mp3</TrackURI><RelTime>00:00:07</RelTime><AbsTime>NOT_IMPLEMENTED</AbsTime><RelCount>-1</RelCount><AbsCount>0</AbsCount></u:GetPositionInfoResponse></s:Body></s:Envelope>'
2024-07-07 07:59:18.322 DEBUG (MainThread) [async_upnp_client.client] Called action: GetPositionInfo, args: {'InstanceID': 0}, response_args: {'Track': 1, 'TrackDuration': '00:03:41', 'TrackMetaData': '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/"><item id="1720331262943" parentID="0" restricted="0"><dc:title>Well Balanced</dc:title><dc:creator>Oliver Shanti &amp; Friends</dc:creator><upnp:artist>Oliver Shanti &amp; Friends</upnp:artist><upnp:actor>Oliver Shanti &amp; Friends</upnp:actor><upnp:author>Oliver Shanti &amp; Friends</upnp:author><upnp:album>10 Years Sattva Music</upnp:album><upnp:genre>Unknown</upnp:genre><upnp:albumArtURI>http://192.168.20.101:49153/content/media/object_id/24/res_id/1/ext/file.jpg</upnp:albumArtURI><res duration="0:03:41" size="7266015" protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.20.101:49153/content/media/object_id/24/res_id/0/group/default/ext/file.mp3</res><upnp:class>object.item.audioItem.musicTrack</upnp:class></item></DIDL-Lite>', 'TrackURI': 'http://192.168.20.101:49153/content/media/object_id/24/res_id/0/group/default/ext/file.mp3', 'RelTime': '00:00:07', 'AbsTime': 'NOT_IMPLEMENTED', 'RelCount': -1, 'AbsCount': 0}

In addition I've checkd how it behaves while playing media via "Browse Media" directly from HA.

When playing form Gerbera DLNA Server as source I see exactly the same problem. Since here "artist" is somehow mapped to "album artist" but "genre" is filled, it fails there there but due to the same reason:

2024-07-07 07:14:20.923 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Got response from POST http://192.168.20.180:8888/Control/oap/AVTransport:
200
Date: Sun, 07 Jul 2024 05:14:20 GMT
Content-Type: text/xml; charset="utf-8"
Content-Encoding: gzip
Ext: 
Server: Linux/4.9.123 UPnP/1.0 GUPnP/0.20.13
Content-Length: 730

b'<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetPositionInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:2"><Track>1</Track><TrackDuration>0:03:41</TrackDuration><TrackMetaData>&lt;DIDL-Lite xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot; xmlns:sec=&quot;http://www.sec.co.kr/&quot;&gt;&lt;item id=&quot;25&quot; parentID=&quot;16&quot; restricted=&quot;1&quot;&gt;&lt;dc:title&gt;Well Balanced&lt;/dc:title&gt;&lt;upnp:class&gt;object.item.audioItem.musicTrack&lt;/upnp:class&gt;&lt;upnp:genre&gt;Chillout &amp; Smooth&lt;/upnp:genre&gt;&lt;upnp:artist&gt;Various Artists&lt;/upnp:artist&gt;&lt;upnp:album&gt;10 Years Sattva Music&lt;/upnp:album&gt;&lt;upnp:originalTrackNumber&gt;1&lt;/upnp:originalTrackNumber&gt;&lt;dc:date&gt;2022&lt;/dc:date&gt;&lt;res protocolInfo=&quot;http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000&quot;&gt;http://192.168.20.101:49153/content/media/object_id/25/res_id/0/group/default/ext/file.mp3&lt;/res&gt;&lt;res protocolInfo=&quot;http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00800000000000000000000000000000&quot;&gt;http://192.168.20.101:49153/content/media/object_id/25/res_id/1/ext/file.jpg&lt;/res&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData><TrackURI>http://192.168.20.101:49153/content/media/object_id/25/res_id/0/group/default/ext/file.mp3</TrackURI><RelTime>0:00:18</RelTime><AbsTime>0:00:18</AbsTime><RelCount>0</RelCount><AbsCount>0</AbsCount></u:GetPositionInfoResponse></s:Body></s:Envelope>'
2024-07-07 07:14:20.926 DEBUG (MainThread) [async_upnp_client.client] Called action: GetPositionInfo, args: {'InstanceID': 0}, response_args: {'Track': 1, 'TrackDuration': '0:03:41', 'TrackMetaData': '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/"><item id="25" parentID="16" restricted="1"><dc:title>Well Balanced</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><upnp:genre>Chillout & Smooth</upnp:genre><upnp:artist>Various Artists</upnp:artist><upnp:album>10 Years Sattva Music</upnp:album><upnp:originalTrackNumber>1</upnp:originalTrackNumber><dc:date>2022</dc:date><res protocolInfo="http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://192.168.20.101:49153/content/media/object_id/25/res_id/0/group/default/ext/file.mp3</res><res protocolInfo="http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=00800000000000000000000000000000">http://192.168.20.101:49153/content/media/object_id/25/res_id/1/ext/file.jpg</res></item></DIDL-Lite>', 'TrackURI': 'http://192.168.20.101:49153/content/media/object_id/25/res_id/0/group/default/ext/file.mp3', 'RelTime': '0:00:18', 'AbsTime': '0:00:18', 'RelCount': 0, 'AbsCount': 0}
2024-07-07 07:14:20.932 ERROR (MainThread) [homeassistant.helpers.entity] Update for media_player.tx_nr696_dlna fails
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1701, in feed
    self.parser.Parse(data, False)
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 351

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 944, in async_update_ha_state
    await self.async_device_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1296, in async_device_update
    await self.async_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 498, in async_update
    await self._device.async_update(do_ping=do_ping)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 360, in async_update
    await self._async_poll_state_variables(
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/profile.py", line 468, in _async_poll_state_variables
    self._on_event(service, changed_state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 400, in _on_event
    self.on_event(service, state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 533, in _on_event
    self.async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 358, in async_write_ha_state
    super().async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1007, in async_write_ha_state
    self._async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1133, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1091, in __async_calculate_state
    if (entity_picture := self.entity_picture) is not None:
                          ^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1068, in entity_picture
    return self.media_image_local
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1073, in media_image_local
    if (image_hash := self.media_image_hash) is None:
                      ^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 639, in media_image_hash
    if (url := self.media_image_url) is not None:
               ^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 894, in media_image_url
    return self._device.media_image_url
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 1198, in media_image_url
    items = _cached_from_xml_string(xml)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 239, in _cached_from_xml_string
    return didl_lite.from_xml_string(xml, strict=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/didl_lite/didl_lite.py", line 1077, in from_xml_string
    xml_el = defusedxml.ElementTree.fromstring(xml_string)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/defusedxml/common.py", line 126, in fromstring
    parser.feed(text)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1703, in feed
    self._raiseerror(v)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1610, in _raiseerror
    raise err
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 351

While playing the track from "My Media" (configuration media_dirs) it looks like the same thing happens. In this case it looks like "TrackURI" which is not escaped correctly:

2024-07-07 08:59:27.197 DEBUG (MainThread) [async_upnp_client.client] Calling action: GetPositionInfo, args: {'InstanceID': 0}
2024-07-07 08:59:27.198 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Sending request:
POST http://192.168.20.180:8888/Control/oap/AVTransport
SOAPAction: "urn:schemas-upnp-org:service:AVTransport:2#GetPositionInfo"
Host: 192.168.20.180:8888
Content-Type: text/xml; charset="utf-8"
<?xml version="1.0"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:2"><InstanceID>0</InstanceID></u:GetPositionInfo></s:Body></s:Envelope>

2024-07-07 08:59:27.219 DEBUG (MainThread) [async_upnp_client.traffic.upnp] Got response from POST http://192.168.20.180:8888/Control/oap/AVTransport:
200
Date: Sun, 07 Jul 2024 06:59:27 GMT
Content-Type: text/xml; charset="utf-8"
Content-Encoding: gzip
Ext: 
Server: Linux/4.9.123 UPnP/1.0 GUPnP/0.20.13
Content-Length: 831

b'<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:GetPositionInfoResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:2"><Track>1</Track><TrackDuration>0:03:41</TrackDuration><TrackMetaData>&lt;DIDL-Lite xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot; xmlns:sec=&quot;http://www.sec.co.kr/&quot;&gt;&lt;item id=&quot;0&quot; parentID=&quot;-1&quot; restricted=&quot;false&quot;&gt;&lt;dc:title&gt;Home Assistant&lt;/dc:title&gt;&lt;upnp:class&gt;object.item.audioItem&lt;/upnp:class&gt;&lt;res protocolInfo=&quot;http-get:*:audio/mpeg:*&quot;&gt;http://192.168.20.101:8123/media/media/01/Sampler/01%20-%20Oliver%20Shanti%20&amp;%20Friends%20-%20Well%20Balanced.mp3?authSig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkMWM2NmRhMWE1OWI0NjIwOTYxYjVmMjBlOTk4NzkzYSIsInBhdGgiOiIvbWVkaWEvbWVkaWEvMDEvU2FtcGxlci8wMSAtIE9saXZlciBTaGFudGkgJiBGcmllbmRzIC0gV2VsbCBCYWxhbmNlZC5tcDMiLCJwYXJhbXMiOltdLCJpYXQiOjE3MjAzMzU1NDgsImV4cCI6MTcyMDQyMTk0OH0.jTfWQ8e5JrhpXH-nJUKjpeEeLrcr-ud9X-728B5R_h4&lt;/res&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;</TrackMetaData><TrackURI>http://192.168.20.101:8123/media/media/01/Sampler/01%20-%20Oliver%20Shanti%20&amp;%20Friends%20-%20Well%20Balanced.mp3?authSig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkMWM2NmRhMWE1OWI0NjIwOTYxYjVmMjBlOTk4NzkzYSIsInBhdGgiOiIvbWVkaWEvbWVkaWEvMDEvU2FtcGxlci8wMSAtIE9saXZlciBTaGFudGkgJiBGcmllbmRzIC0gV2VsbCBCYWxhbmNlZC5tcDMiLCJwYXJhbXMiOltdLCJpYXQiOjE3MjAzMzU1NDgsImV4cCI6MTcyMDQyMTk0OH0.jTfWQ8e5JrhpXH-nJUKjpeEeLrcr-ud9X-728B5R_h4</TrackURI><RelTime>0:00:09</RelTime><AbsTime>0:00:09</AbsTime><RelCount>0</RelCount><AbsCount>0</AbsCount></u:GetPositionInfoResponse></s:Body></s:Envelope>'
2024-07-07 08:59:27.223 DEBUG (MainThread) [async_upnp_client.client] Called action: GetPositionInfo, args: {'InstanceID': 0}, response_args: {'Track': 1, 'TrackDuration': '0:03:41', 'TrackMetaData': '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:sec="http://www.sec.co.kr/"><item id="0" parentID="-1" restricted="false"><dc:title>Home Assistant</dc:title><upnp:class>object.item.audioItem</upnp:class><res protocolInfo="http-get:*:audio/mpeg:*">http://192.168.20.101:8123/media/media/01/Sampler/01%20-%20Oliver%20Shanti%20&%20Friends%20-%20Well%20Balanced.mp3?authSig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkMWM2NmRhMWE1OWI0NjIwOTYxYjVmMjBlOTk4NzkzYSIsInBhdGgiOiIvbWVkaWEvbWVkaWEvMDEvU2FtcGxlci8wMSAtIE9saXZlciBTaGFudGkgJiBGcmllbmRzIC0gV2VsbCBCYWxhbmNlZC5tcDMiLCJwYXJhbXMiOltdLCJpYXQiOjE3MjAzMzU1NDgsImV4cCI6MTcyMDQyMTk0OH0.jTfWQ8e5JrhpXH-nJUKjpeEeLrcr-ud9X-728B5R_h4</res></item></DIDL-Lite>', 'TrackURI': 'http://192.168.20.101:8123/media/media/01/Sampler/01%20-%20Oliver%20Shanti%20&%20Friends%20-%20Well%20Balanced.mp3?authSig=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkMWM2NmRhMWE1OWI0NjIwOTYxYjVmMjBlOTk4NzkzYSIsInBhdGgiOiIvbWVkaWEvbWVkaWEvMDEvU2FtcGxlci8wMSAtIE9saXZlciBTaGFudGkgJiBGcmllbmRzIC0gV2VsbCBCYWxhbmNlZC5tcDMiLCJwYXJhbXMiOltdLCJpYXQiOjE3MjAzMzU1NDgsImV4cCI6MTcyMDQyMTk0OH0.jTfWQ8e5JrhpXH-nJUKjpeEeLrcr-ud9X-728B5R_h4', 'RelTime': '0:00:09', 'AbsTime': '0:00:09', 'RelCount': 0, 'AbsCount': 0}
2024-07-07 08:59:27.233 ERROR (MainThread) [homeassistant.helpers.entity] Update for media_player.tx_nr696_dlna fails
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1701, in feed
    self.parser.Parse(data, False)
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 444

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 944, in async_update_ha_state
    await self.async_device_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1296, in async_device_update
    await self.async_update()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 498, in async_update
    await self._device.async_update(do_ping=do_ping)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 360, in async_update
    await self._async_poll_state_variables(
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/profile.py", line 468, in _async_poll_state_variables
    self._on_event(service, changed_state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 400, in _on_event
    self.on_event(service, state_variables)
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 533, in _on_event
    self.async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 358, in async_write_ha_state
    super().async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1007, in async_write_ha_state
    self._async_write_ha_state()
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1133, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/helpers/entity.py", line 1091, in __async_calculate_state
    if (entity_picture := self.entity_picture) is not None:
                          ^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1068, in entity_picture
    return self.media_image_local
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 1073, in media_image_local
    if (image_hash := self.media_image_hash) is None:
                      ^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/media_player/__init__.py", line 639, in media_image_hash
    if (url := self.media_image_url) is not None:
               ^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/homeassistant/components/dlna_dmr/media_player.py", line 894, in media_image_url
    return self._device.media_image_url
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 1198, in media_image_url
    items = _cached_from_xml_string(xml)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/async_upnp_client/profiles/dlna.py", line 239, in _cached_from_xml_string
    return didl_lite.from_xml_string(xml, strict=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/didl_lite/didl_lite.py", line 1077, in from_xml_string
    xml_el = defusedxml.ElementTree.fromstring(xml_string)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/srv/homeassistant/lib/python3.12/site-packages/defusedxml/common.py", line 126, in fromstring
    parser.feed(text)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1703, in feed
    self._raiseerror(v)
  File "/usr/local/lib/python3.12/xml/etree/ElementTree.py", line 1610, in _raiseerror
    raise err
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 444

Everything is pointing to the renderer and should be the proove that Onkyo didn't implement it the right way and I would be more than happy if you really find a way to handle this kind of behaviour in async-upnp-client.