From c3cd9cf0abfb00f08185eb34f6f8ab0535a0d1b6 Mon Sep 17 00:00:00 2001
From: sethg <sethg@geographika.co.uk>
Date: Tue, 18 Mar 2025 22:32:54 +0100
Subject: [PATCH] Test for xml in response, regardless of mimetype

---
 owslib/util.py     |  4 +++-
 tests/test_util.py | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/owslib/util.py b/owslib/util.py
index 3165b484..12c73400 100644
--- a/owslib/util.py
+++ b/owslib/util.py
@@ -346,8 +346,10 @@ def getXMLTree(rsp: ResponseWrapper) -> etree:
     content_type = rsp.info().get('Content-Type', 'text/xml')
     url = rsp.geturl()
 
+    has_xml_tag = raw_text.lstrip().startswith(b'<?xml')
+
     xml_types = ['text/xml', 'application/xml', 'application/vnd.ogc.wms_xml']
-    if not any(xt in content_type.lower() for xt in xml_types):
+    if not any(xt in content_type.lower() for xt in xml_types) and not has_xml_tag:
         html_body = et.find('BODY')  # note this is case-sensitive
         if html_body is not None and len(html_body.text) > 0:
             response_text = html_body.text.strip("\n")
diff --git a/tests/test_util.py b/tests/test_util.py
index 7bccee26..4db76189 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -71,6 +71,20 @@ def test_getXMLTree_valid():
     assert et.find('.//Title').text == "Example"
 
 
+def test_getXMLTree_non_xml_mime_type():
+
+    mock_resp = mock.Mock()
+    mock_resp.url = 'http:///example.org/?service=WFS&request=GetCapabilities&version=2.0.0'
+    mock_resp.content = b'<?xml version="1.0" encoding="UTF-8"?>\n<WFS_Capabilities><ServiceIdentification>' \
+                        b'<Title>Example</Title></ServiceIdentification></WFS_Capabilities>'
+    # test with a non-XML mime type, but the response starts with <?xml
+    mock_resp.headers = {'Content-Type': 'application/octet-stream'}
+    resp_wrap = ResponseWrapper(mock_resp)
+
+    et = getXMLTree(resp_wrap)
+    assert et.find('.//Title').text == "Example"
+
+
 def test_getXMLTree_valid_missing_content_type():
 
     mock_resp = mock.Mock()