geostyler / geostyler-qgis-parser

GeoStyler Style Parser implementation for QGIS
https://geostyler.org
BSD 2-Clause "Simplified" License
16 stars 9 forks source link

QML style from QGIS 3.28 cannot be parsed #455

Open jmacura opened 1 year ago

jmacura commented 1 year ago

Question

Hello, I am failing to parse any QML file created in QGIS 3.28. Looking in the code, there seem to be a significantly different inner structure of the <symbol> element. I am attaching a short example below. It should be a rough equivalent to https://github.com/geostyler/geostyler-qgis-parser/blob/master/data/qmls/polygon_simple.qml – a fill symbol with color, outline color and outline width.

super-ugly-zones_only-symbology.zip

<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.28.3-Firenze" styleCategories="Symbology">
  <renderer-v2 type="singleSymbol" referencescale="-1" enableorderby="0" forceraster="0" symbollevels="0">
    <symbols>
      <symbol type="fill" frame_rate="10" alpha="1" force_rhr="0" name="0" clip_to_extent="1" is_animated="0">
        <data_defined_properties>
          <Option type="Map">
            <Option type="QString" value="" name="name"/>
            <Option name="properties"/>
            <Option type="QString" value="collection" name="type"/>
          </Option>
        </data_defined_properties>
        <layer pass="0" locked="0" enabled="1" class="SimpleFill">
          <Option type="Map">
            <Option type="QString" value="3x:0,0,0,0,0,0" name="border_width_map_unit_scale"/>
            <Option type="QString" value="1,225,255,255" name="color"/>
            <Option type="QString" value="bevel" name="joinstyle"/>
            <Option type="QString" value="0,0" name="offset"/>
            <Option type="QString" value="3x:0,0,0,0,0,0" name="offset_map_unit_scale"/>
            <Option type="QString" value="MM" name="offset_unit"/>
            <Option type="QString" value="36,164,0,255" name="outline_color"/>
            <Option type="QString" value="solid" name="outline_style"/>
            <Option type="QString" value="1.06" name="outline_width"/>
            <Option type="QString" value="MM" name="outline_width_unit"/>
            <Option type="QString" value="solid" name="style"/>
          </Option>
          <data_defined_properties>
            <Option type="Map">
              <Option type="QString" value="" name="name"/>
              <Option name="properties"/>
              <Option type="QString" value="collection" name="type"/>
            </Option>
          </data_defined_properties>
        </layer>
      </symbol>
    </symbols>
    <rotation/>
    <sizescale/>
  </renderer-v2>
  <blendMode>0</blendMode>
  <featureBlendMode>0</featureBlendMode>
  <layerGeometryType>2</layerGeometryType>
</qgis>

Parsing this QML with geostyler-qgis-parser leaves me with a following error (trimmed): image

Related issue in hslayers: https://github.com/hslayers/hslayers-ng/issues/3513

Could you please confirm that the issue is relevant? Is there a change in the way QGIS is exporting QML files which is not yet reflected in geostyler? I went through the QGIS visual changelogs but I have found no mention about any change in this regard (until version 3.30 which is not yet relevant as I am using 3.28)... Thanks!

KaiVolland commented 1 year ago

Hi, thanks for the report. Currently the qgisparser supports very simple styles like https://github.com/geostyler/geostyler-qgis-parser/blob/master/data/qmls/polygon_simple.qml

As the symbolization features in QGis are almost endless i'm not sure what could have change. But as the post style is still "renderer-v2" i would assume that it should work. If not the error message should be more speaking. I'll check your qgis files and add more feedback if possible.

KaiVolland commented 1 year ago

I have a qgis 3.22.4 runnig on my system. If i import and export and your style it looks different and can be parsed with the geostyler-qgis-parser in the demo: ping.qml.zip

Unfortunately i wont have time to debug into this deeper nor to fix it. It would be great if you could find some time to dig deeper here.

OSHistory commented 1 year ago

I can confirm that the error exists. It probably stems from the fact, that the new XML-Structure is as follows (Root <Option> tag with <Option /> children.

<layer>
 <Option>
  <!-- multiple nested Options -->
  <Option />
</Option>
</layer>

Used to be direct propchildren to <layer>:

<layer>
 <prop />
</layer>

This is why the following function fails, as there are no props.

/**
   *
   * @param qmlSymbolizer
   */
  qmlSymbolizerLayerPropsToObject(qmlSymbolizer: any) {
    const qmlMarkerProps: any = {};
    qmlSymbolizer.prop.forEach((prop: QmlProp) => {
      const key = prop.$.k;
      const value = prop.$.v;
      qmlMarkerProps[key] = value;
    });
    return qmlMarkerProps;
  }

I'd be happy to look into it, but probably would need a short introduction from one member of the core-Team on how parsers are implemented and how the dev setup works.

I added a screenshot for illustration:

Screenshot from 2023-05-13 18-39-13

OSHistory commented 1 year ago

I have created a work in progress. I converted all of the styles through a 3.28 Firenze QGIS to the new schema. The Parser correctly reads <Option> instead of <prop> and also writes correctly. It needs to register under the root <Option type="Map"> The write tests fail, probably the testing files should be stripped by all non necessary tags. The branch is in my fork: https://github.com/OSHistory/geostyler-qgis-parser/tree/readQGIS228