Repository: qgis/QGIS
Pull request #61878: [Tests] Fix PyQgsSymbolLayerReadSld and PyQgsMapBoxGlStyleConverter on QT6
Author: login: rouault
Created: 2025-05-16T23:50:11Z | Merged: 2025-05-19T22:53:14Z



Diff:
diff --git a/.ci/test_blocklist_qt6.txt b/.ci/test_blocklist_qt6.txt
index 03df9be6c8cf..e615eff764bf 100644
--- a/.ci/test_blocklist_qt6.txt
+++ b/.ci/test_blocklist_qt6.txt
@@ -38,10 +38,8 @@ PyQgsAuthenticationSystem
 PyQgsEditWidgets
 PyQgsElevationProfileCanvas
 PyQgsLayoutHtml
-PyQgsMapBoxGlStyleConverter
 PyQgsPalLabelingPlacement
 PyQgsRasterLayerRenderer
-PyQgsSymbolLayerReadSld
 PyQgsSettings
 PyQgsSettingsEntry
 PyQgsServerAccessControlWFSTransactional
diff --git a/src/core/qgscolorutils.cpp b/src/core/qgscolorutils.cpp
index 4c37a41d2412..204419e038a8 100644
--- a/src/core/qgscolorutils.cpp
+++ b/src/core/qgscolorutils.cpp
@@ -220,10 +220,10 @@ QString QgsColorUtils::colorToString( const QColor &color )
       qreal alpha = 1;
 #endif
       color.getRgbF( &red, &green, &blue, &alpha );
-      return compatString + QStringLiteral( "rgb:%1,%2,%3,%4" ).arg( qgsDoubleToString( red ),
-             qgsDoubleToString( green ),
-             qgsDoubleToString( blue ),
-             qgsDoubleToString( alpha ) );
+      return compatString + QStringLiteral( "rgb:%1,%2,%3,%4" ).arg( qgsDoubleToString( red, 7 ),
+             qgsDoubleToString( green, 7 ),
+             qgsDoubleToString( blue, 7 ),
+             qgsDoubleToString( alpha, 7 ) );
     }
 
     case QColor::Hsv:
diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp
index 37749d8ae1a8..c8f102dc0938 100644
--- a/src/core/qgsmaplayer.cpp
+++ b/src/core/qgsmaplayer.cpp
@@ -66,6 +66,7 @@
 #include <QStandardPaths>
 #include <QUuid>
 #include <QRegularExpression>
+#include <QXmlStreamReader>
 
 #include <sqlite3.h>
 
@@ -2292,14 +2293,32 @@ QString QgsMapLayer::loadSldStyle( const QString &uri, bool &resultFlag )
   QDomDocument myDocument;
 
   // location of problem associated with errorMsg
-  int line, column;
+  int line = 0, column = 0;
   QString myErrorMessage;
 
   QFile myFile( uri );
   if ( myFile.open( QFile::ReadOnly ) )
   {
     // read file
+#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
+    QXmlStreamReader xmlReader( &myFile );
+    xmlReader.addExtraNamespaceDeclaration( QXmlStreamNamespaceDeclaration( QStringLiteral( "sld" ), QStringLiteral( "http://www.opengis.net/sld" ) ) );
+    xmlReader.addExtraNamespaceDeclaration( QXmlStreamNamespaceDeclaration( QStringLiteral( "fes" ), QStringLiteral( "http://www.opengis.net/fes/2.0" ) ) );
+    xmlReader.addExtraNamespaceDeclaration( QXmlStreamNamespaceDeclaration( QStringLiteral( "ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) ) );
+    const QDomDocument::ParseResult result = myDocument.setContent( &xmlReader, QDomDocument::ParseOption::UseNamespaceProcessing );
+    if ( result )
+    {
+      resultFlag = true;
+    }
+    else
+    {
+      myErrorMessage = result.errorMessage;
+      line = result.errorLine;
+      column = result.errorColumn;
+    }
+#else
     resultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
+#endif
     if ( !resultFlag )
       myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
     myFile.close();
diff --git a/tests/src/python/test_qgsmapboxglconverter.py b/tests/src/python/test_qgsmapboxglconverter.py
index c5afd06b934c..0e9ab826709e 100644
--- a/tests/src/python/test_qgsmapboxglconverter.py
+++ b/tests/src/python/test_qgsmapboxglconverter.py
@@ -1491,14 +1491,14 @@ def testCircleLayer(self):
         expected_properties = {
             "angle": "0",
             "cap_style": "square",
-            "color": "22,22,22,153,rgb:0.08627450980392157,0.08627450980392157,0.08627450980392157,0.59999999999999998",
+            "color": "22,22,22,153,rgb:0.0862745,0.0862745,0.0862745,0.6",
             "horizontal_anchor_point": "1",
             "joinstyle": "bevel",
             "name": "circle",
             "offset": "11,22",
             "offset_map_unit_scale": "3x:0,0,0,0,0,0",
             "offset_unit": "Pixel",
-            "outline_color": "46,46,46,128,rgb:0.1803921568627451,0.1803921568627451,0.1803921568627451,0.50000762951094835",
+            "outline_color": "46,46,46,128,rgb:0.1803922,0.1803922,0.1803922,0.5000076",
             "outline_style": "solid",
             "outline_width": "3",
             "outline_width_map_unit_scale": "3x:0,0,0,0,0,0",
@@ -2675,10 +2675,21 @@ def testRetrieveSprite(self):
                 icon_image, context
             )
         )
-        self.assertEqual(
-            sprite_property,
-            "CASE WHEN \"class\" IN ('sinkhole') THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAAAwAAAAgCAYAAAAmG5mqAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAArklEQVQ4jWNmQAPxrgr1EzIMDiS4KjQwMDAwXLz34SCyPBO6BkJgVMOohlEN9NTA2JWit8NUTcidGMWnb73bybT60NM+Yk1ffehpH9PpW293nb71bicxpp++9XYXE0wnMaYzMEA9TcgWmOlwDYRsQZaDa8BlC7LpKBpw2YIuhqIB3RZ00zE0oJuIzUYWTDcjbEE3nYGBgYEZXYCBgYHhw5c/r649/Hz82dvvd9HlANtvdC5jaNf5AAAAAElFTkSuQmCC' WHEN \"class\" IN ('sinkhole_rock','sinkhole_scree') THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAAAwAAAAgCAYAAAAmG5mqAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAoUlEQVQ4je2PMRLCIBBFv8QzcAbOwNB7LD1BzmNSaeUl8AJ/GDoKOhvDJGsyUFmxJct7DwaIMcZcnXMPY8wNAEIIz/VeSaA2HehAB/4JnKy1d631peUyyUl578dWu/d+VCRnklOLneSsFrLFDnw/Xass9gLUKutdAY4qa/sGOKrIsw0gK9L+A0jjXvG88+ZSkXYAGOQBAOScGWN8pZTecvcBJ6N45xp02+cAAAAASUVORK5CYII=' WHEN \"class\" IN ('sinkhole_ice','sinkhole_water') THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAAAwAAAAgCAYAAAAmG5mqAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAq0lEQVQ4jWNgQAOSXmn1xlPO/jeecva/pFdaPbo8E7oAITCqYVTDqAZ6amBUzZ6yg0/T0p0YxZ+uH9/J9HLf0j5iTX+5b2kf06frx3d9un58JzGmf7p+fBcTTCcxpjMwQD1NyBaY6XANhGxBloNrwGULsukoGnDZgi6GogHdFnTTMTSgm4jNRhYsbobbgm46AwMDAzO6AAMDA8OfL+9ffb1/+fjPN0/uossBAN+ec6mo5jjFAAAAAElFTkSuQmCC' ELSE '' END",
-        )
+
+        def strip_base64(s):
+            pos = 0
+            while True:
+                pos = s.find("'base64:", pos)
+                if pos < 0:
+                    break
+                end_pos = s.find("'", pos + 1)
+                assert end_pos > pos
+                s = s[0:pos] + "'base64:[snip]'" + s[end_pos + 1 :]
+                pos += len("'base64:")
+            return s
+
+        expected = "CASE WHEN \"class\" IN ('sinkhole') THEN 'base64:[snip]' WHEN \"class\" IN ('sinkhole_rock','sinkhole_scree') THEN 'base64:[snip]' WHEN \"class\" IN ('sinkhole_ice','sinkhole_water') THEN 'base64:[snip]' ELSE '' END"
+        self.assertEqual(strip_base64(sprite_property), expected)
 
         # swisstopo - lightbasemap - place_village
         icon_image = [
@@ -2699,10 +2710,8 @@ def testRetrieveSprite(self):
                 icon_image, context
             )
         )
-        self.assertEqual(
-            sprite_property,
-            "CASE WHEN @vector_tile_zoom >= 12 THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA9hAAAPYQGoP6dpAAACDUlEQVQ4jZ2VsaraYBTH/8mFTAfJ4NBBJBAHcdCMHTLkES7oA6Rv0D5BvU9gQRyKQ/MCgt3qpGBcdImLyRAhg4hgwIDHxSUd2s/eek24+ptCkvP7zjk5nEjIoFgsPhNRQ1VVi4gMAGBmL0mSyel08vb7/c9bcdL1DSIyqtXqDyHJgpm9IAg+MbOXKdQ0ra1p2lcA0HUdpmnCMAxUKhUAQBiG8DwPrutivV4DAKIoakdR9PLmRE3T2pZlpZZlpd1uNz0ej2kWx+Mx7Xa7qXi/VCp9flOmeDidTjNF10yn04tUtOgJAOr1+i9FUT40m020Wq281v1HuVwGM8P3fRQKhY/b7fa7LL6mruuwbfvdMoFt29B1HURkFIvFZ1mkapomiOhuIRHBNE1xbciqqloAYBi5U5KLiFVV1bpkKEbjEUQsETXkhy23kWQx6WEYPmwRsczsyUmSTADA87y8mFxEbJIkk0uGs9kMzHy3jJkxGo3+ZRjH8ZCZl2EYwnGcu4WO42C324GZl3EcD2UACILABoDBYADXdd8tc10Xg8EArx1PAHA+n3cAJFVVrfF4jNPphFqtBkVRMsvs9/vo9XoAgDAMv8RxPLwIgT8NFdLVaoXFYoHD4QBJkkBEOJ/P8H0fo9EInU4H8/n8IttsNt+EJ2vBOkTUyCuXmZdBENi5C/Y1f5eGcesXwMyeKPGa3yGWS8B8xv1iAAAAAElFTkSuQmCC'  WHEN @vector_tile_zoom >= 10 THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAABs0lEQVQ4jY2TMW/iMBiG37iM5hQhDwyZUIYTQmruF+AtkTKU+yeMt9Dh/sDdDezlH9At3liQbksGJJYE3ZAhSBbKQaQiS8Rd6opSaHk3W8/7+vtsfxZORCn1GGN3tm1zSqkHAFVVJWVZzqSUj1VVJce8dbxwHGfouu6v01AjrfU2y7L7PM//vAvo9XpTxtgdAPi+jyAI4LouACBNU0RRBCEEAEBKOV0sFt/fnMw512EY6jiO9SXFcazDMNScc+04zvC1Z8655px/aD4O4Zzrfr//n1LqEcbYwJTted6l9l/leR5834dlWV8YYwNi2zYHgCAIPjUbGda2bU7MU5kLu0aGpZTekqtd52UR8zHSNL3aZdiqqhJSluUMAKIoujrAsGVZzoiUclrX9U4IgSRJPrECSZJACIG6rndFUTzcKKWKw+Hw1Gq1gvl8jm63i3a7fdE8Go2glEKWZT82m010AwDb7fYvpfRbo9H4KoTAer1Gs9kEpRRKKSyXS0wmE4zHYyilIKV8TNN0CJwZpk6n85MQ0jxXQV3Xu9VqdZ/n+W+zZ51CL+M8ODfORVE87Pf7f8f8M97/C1rlJ2QfAAAAAElFTkSuQmCC'  WHEN @vector_tile_zoom >= 8 THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAA9hAAAPYQGoP6dpAAABEElEQVQokXWSMW7CQBBFnx1EtcVKNFOmcIkU9xQsN0gk99kbkJ4TcIvNARA5AtxgkFyafkW1xZZITpEYUdiv/l8z8/8UPCEiXkQ+jTE1QM5ZY4whxvg9aAqA2Wxml8vl0VrrGCGldGrb9uN+v6cCoK7rk7V2vVqtaJqGqqowxqCqhBC4XC6klE6qukFEvHOu3+12/RTb7bZ3zvUi4ksR8QBN04xtA4D3/nFjORxY1/WkoaoqAIwxb+WkapyizDkrgKpOqrquA/5iLmOMAeBwOEwaQggAxBjDS85ZrbWb2+32er1eWSwWGGOYz+eoKvv9foj13HXd13NxP9ba9diElNK5bdv3R3ED/6/hR14jDJpfqBeVnGzOJRAAAAAASUVORK5CYII='  WHEN @vector_tile_zoom >= 6 THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAv0lEQVQYlYXOIQqDYBiH8b/6IW8wOPiCAxFXTIZ1i97AbFsw7wbCbjHwAMZdwcU11wwG0aLtRcQgwlYXhP0O8PAoACCljG3bvhqGcRZCmMxctm17Y+ZSkVLGvu8/sKOqqkjzPO9ORG4QBMiyDEmSYBgG9H0PIjopYRh+AKAoCliWBQBomgZpmmLbNlb30j8UzTTNiIjccRzhOA7WdUWe5+i6DtM0vf5PLstSz/P81nX9KIQ4qKpKzPys6/rCzOUX/GBLMm760HoAAAAASUVORK5CYII=' ELSE 'base64:iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAv0lEQVQYlYXOIQqDYBiH8b/6IW8wOPiCAxFXTIZ1i97AbFsw7wbCbjHwAMZdwcU11wwG0aLtRcQgwlYXhP0O8PAoACCljG3bvhqGcRZCmMxctm17Y+ZSkVLGvu8/sKOqqkjzPO9ORG4QBMiyDEmSYBgG9H0PIjopYRh+AKAoCliWBQBomgZpmmLbNlb30j8UzTTNiIjccRzhOA7WdUWe5+i6DtM0vf5PLstSz/P81nX9KIQ4qKpKzPys6/rCzOUX/GBLMm760HoAAAAASUVORK5CYII=' END",
-        )
+        expected = "CASE WHEN @vector_tile_zoom >= 12 THEN 'base64:[snip]'  WHEN @vector_tile_zoom >= 10 THEN 'base64:[snip]'  WHEN @vector_tile_zoom >= 8 THEN 'base64:[snip]'  WHEN @vector_tile_zoom >= 6 THEN 'base64:[snip]' ELSE 'base64:[snip]' END"
+        self.assertEqual(strip_base64(sprite_property), expected)
 
         # swisstopo - lightbasemap - lake_elevation
         icon_image = [
@@ -2718,10 +2727,9 @@ def testRetrieveSprite(self):
                 icon_image, context
             )
         )
-        self.assertEqual(
-            sprite_property,
-            "CASE WHEN \"lake_depth\" IS NOT NULL THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAADAAAAAmCAYAAACCjRgBAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAA3UlEQVRYhe3WMQrCMBgF4Nfo7C0cnDt5Ar2LnsWpHsE72A6umTo5ZBBxcVEEIeggCHVxCKWtLUj/BN63tfzD/16gTYSW4iQv2s72SUkvQERERER/FCd54evNs0rwt1EGkMYA0hhAGgNIYwBpDCAtGi+S7WgynTUNWaPTw3o572upLtRlt1n9GmozI0VZozNrdFo3YI1OrdFZn0t1oYDmhn1uH/gGqDsF39sHnK9QVdO+tw84AcqnEEL7QOk/4DYeQvsAMHQf3FMIoX0AGJRfvB/36/O016/b+SixUFcfqsZi6d4Ghu0AAAAASUVORK5CYII='  WHEN length(to_string(\"ele\")) IS 3 THEN 'base64:iVBORw0KGgoAAAANSUhEUgAAACQAAAAECAYAAADmrJ2uAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAGElEQVQokWM0nnL2P8MgAkwD7YBRQCoAANWHApf/BqmbAAAAAElFTkSuQmCC' ELSE 'base64:iVBORw0KGgoAAAANSUhEUgAAADAAAAAECAYAAADI6bw8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAAGElEQVQokWM0nnL2P8MQBkwD7YBRMNQBAMaFApc4aKj/AAAAAElFTkSuQmCC' END",
-        )
+        expected = "CASE WHEN \"lake_depth\" IS NOT NULL THEN 'base64:[snip]'  WHEN length(to_string(\"ele\")) IS 3 THEN 'base64:[snip]' ELSE 'base64:[snip]' END"
+        self.assertEqual(strip_base64(sprite_property), expected)
+
         self.assertEqual(
             sprite_size_property,
             'CASE WHEN "lake_depth" IS NOT NULL THEN 24  WHEN length(to_string("ele")) IS 3 THEN 18 ELSE 24 END',
diff --git a/tests/src/python/test_qgssymbollayer_readsld.py b/tests/src/python/test_qgssymbollayer_readsld.py
index 25920585512d..c073dd4d6238 100644
--- a/tests/src/python/test_qgssymbollayer_readsld.py
+++ b/tests/src/python/test_qgssymbollayer_readsld.py
@@ -138,7 +138,7 @@ def testLineOpacity():
             # stroke-opacity=0.1
             self.assertEqual(
                 props["line_color"],
-                "0,62,186,25,rgb:0,0.24313725490196078,0.72941176470588232,0.09803921568627451",
+                "0,62,186,25,rgb:0,0.2431373,0.7294118,0.0980392",
             )
 
         testLineColor()
@@ -467,7 +467,7 @@ def testLineOpacity():
             # stroke-opacity=0.1
             self.assertEqual(
                 props["line_color"],
-                "0,62,186,24,rgb:0,0.24313725490196078,0.72941176470588232,0.09411764705882353",
+                "0,62,186,24,rgb:0,0.2431373,0.7294118,0.0941176",
             )
 
         testLineColor()


Reviews:
user: login: nyalldawson
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T20:18:36Z
user: login: rouault
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T20:56:41Z
user: login: nyalldawson
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-19T00:07:38Z
user: login: rouault
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T09:53:41Z
user: login: nyalldawson
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-19T22:52:58Z

Review comments:
diff_hunk: @@ -507,7 +507,7 @@ def test_read_circle(self):
         """Test wellknown name circle polygon fill"""
 
         sld = """<?xml version="1.0" encoding="UTF-8"?>
-            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
+            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
path: tests/src/python/test_qgssymbollayer_readsld.py
user: login: nyalldawson
body: Doesn't this change what the test is checking? Presumably some tool output the original (invalid?) XML...
created_at: 2025-05-17T20:18:36Z
author_association: COLLABORATOR
diff_hunk: @@ -507,7 +507,7 @@ def test_read_circle(self):
         """Test wellknown name circle polygon fill"""
 
         sld = """<?xml version="1.0" encoding="UTF-8"?>
-            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
+            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
path: tests/src/python/test_qgssymbollayer_readsld.py
user: login: rouault
body: Using a namespace without defining it with the xmlns: attribute is invalid XML. Cf
```
$ echo "<sld:foo/>" | xmllint --format -
-:1: namespace error : Namespace prefix sld on foo is not defined
<sld:foo/>
        ^
<?xml version="1.0"?>
<sld:foo/>
```
vs

```
$ echo "<sld:foo xmlns:sld='something'/>" | xmllint --format -
<?xml version="1.0"?>
<sld:foo xmlns:sld="something"/>
```

created_at: 2025-05-17T20:56:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -507,7 +507,7 @@ def test_read_circle(self):
         """Test wellknown name circle polygon fill"""
 
         sld = """<?xml version="1.0" encoding="UTF-8"?>
-            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
+            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
path: tests/src/python/test_qgssymbollayer_readsld.py
user: login: nyalldawson
body: Hmm - I'm still nervous that some tool out there is generating this content, and would lean towards just being tolerant and handling this automatically if we can.

Could we use a similar approach to https://github.com/qgis/QGIS/pull/61690/files#diff-2b31f4f76dacb4bd2240768e67fbe59d416219b9b58b3fece7706a1ebb18fbaeR3569 ?
created_at: 2025-05-19T00:07:38Z
author_association: COLLABORATOR
diff_hunk: @@ -507,7 +507,7 @@ def test_read_circle(self):
         """Test wellknown name circle polygon fill"""
 
         sld = """<?xml version="1.0" encoding="UTF-8"?>
-            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
+            <StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
path: tests/src/python/test_qgssymbollayer_readsld.py
user: login: rouault
body: > Could we use a similar approach to

thanks for the hint! pull request updated accordingly
created_at: 2025-05-19T09:53:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-17T00:31:06Z
body: <!-- !!## stickymarker ##!! -->

<!-- ====startsection mingw64-qt6-->
### 🪟 Windows Qt6 builds
Download [Windows Qt6 builds of this PR for testing](https://github.com/qgis/QGIS/actions/runs/15109895600/artifacts/3150740101).
*(Built from commit 1d523fa4eba46ccaa02858f22efd8188c57c1e3f)*

<!-- ====endsection mingw64-qt6-->

<!-- ====startsection mingw64-->
### 🪟 Windows builds
Download [Windows builds of this PR for testing](https://github.com/qgis/QGIS/actions/runs/15109895596/artifacts/3150939988).
Debug symbols for this build are available [here](https://github.com/qgis/QGIS/actions/runs/15109895596/artifacts/3150940449).
*(Built from commit 1d523fa4eba46ccaa02858f22efd8188c57c1e3f)*

<!-- ====endsection mingw64-->

author_association: CONTRIBUTOR
user: login: nyalldawson
created_at: 2025-05-19T22:53:11Z
body: Thanks @rouault !
author_association: COLLABORATOR