4

I need to figure out how to make elsefilter work when imported into QGIS (2.8.3) via sld.

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
<NamedLayer>
<se:Name>dopravni_znacky</se:Name>
<UserStyle>
  <se:Name>dopravni_znacky</se:Name>
  <se:FeatureTypeStyle>
    <se:Rule>
      <se:Name></se:Name>
      <se:ElseFilter/>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:Mark>
            <se:WellKnownName>circle</se:WellKnownName>
            <se:Fill>
              <se:SvgParameter name="fill">#991321</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#000000</se:SvgParameter>
            </se:Stroke>
          </se:Mark>
          <se:Size>2</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>
    <se:Rule>
      <se:Name></se:Name>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>umisteni</ogc:PropertyName>
          <ogc:Literal>v chodníku</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:ExternalGraphic>
            <se:OnlineResource xlink:type="simple" xlink:href="transport/transport_aerodrome.svg"/>
            <se:Format>image/svg+xml</se:Format>
          </se:ExternalGraphic>
          <se:Size>10</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>
  </se:FeatureTypeStyle>
</UserStyle>

When I use this sld, these styles overwrite each other (I see two overlapping icons), I want the first style to be shown only when the conditions are not met.

  • Should not be <se:ElseFilter/> but <sld:ElseFilter/>? does not work either way. – Drake Zet Jan 25 '16 at 14:17
4

As you can read here about the ElseFilter,

A Rule containing an ElseFilter is evaluated if and only if no other Rule in the current Style matches. All Rules in a Style are evaluated sequentially from top to bottom, testing each Rule's Filter against the current Object.

This means that you have to list all your rules, and your last rule should contain the ElseFilter (I have changed the rules' order in your code). However, if you only do that, QGIS will ignore the first rule, because PropertyIsEqualTo applies to all your objects, so it styles them twice. So you have to add a new filter to the last rule, PropertyIsNotEqualTo, to eliminate your problem.

Here is your modified (working) code:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
<NamedLayer>
<se:Name>dopravni_znacky</se:Name>
<UserStyle>
  <se:Name>dopravni_znacky</se:Name>
  <se:FeatureTypeStyle>
    <se:Rule>
      <se:Name></se:Name>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>umisteni</ogc:PropertyName>
          <ogc:Literal>v chodníku</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:ExternalGraphic>
            <se:OnlineResource xlink:type="simple" xlink:href="transport/transport_aerodrome.svg"/>
            <se:Format>image/svg+xml</se:Format>
          </se:ExternalGraphic>
          <se:Size>10</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>
    <se:Rule>
      <se:Name></se:Name>
      <se:ElseFilter/>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsNotEqualTo>
          <ogc:PropertyName>umisteni</ogc:PropertyName>
          <ogc:Literal>v chodníku</ogc:Literal>
        </ogc:PropertyIsNotEqualTo>
      </ogc:Filter>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:Mark>
            <se:WellKnownName>circle</se:WellKnownName>
            <se:Fill>
              <se:SvgParameter name="fill">#991321</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#000000</se:SvgParameter>
            </se:Stroke>
          </se:Mark>
          <se:Size>2</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>  
  </se:FeatureTypeStyle>
</UserStyle>

It is stated here that QGIS ELSE expression is a bug, as you said earlier.

If you select 'Categorized' to style your features (considering that you have uncategorized/else features), QGIS listens and shows them accordingly. But if you go to Rule-based, even tough QGIS styles the ELSE category differently, these features are styled twice.

ELSE category

After I exported the sld that QGIS created, I saw this:

<!--Parser Error: syntax error, unexpected ELSE - Expression was: ELSE-->

So QGis cannot render the ELSE filter.

As a workaround (I don't know if you can use this, you said that you have a lot of conditions) you can try this:

First, list all your conditions, based on PropertyIsEqualTo (without using the ElseFilter):

    <se:Rule>
      <se:Name></se:Name>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>type</ogc:PropertyName>
          <ogc:Literal>condition1</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <se:PolygonSymbolizer>
        <se:Fill>
          <se:SvgParameter name="fill">#de0000</se:SvgParameter>
        </se:Fill>
        <se:Stroke>
          <se:SvgParameter name="stroke">#000000</se:SvgParameter>
          <se:SvgParameter name="stroke-opacity">0.00</se:SvgParameter>
          <se:SvgParameter name="stroke-width">0.26</se:SvgParameter>
          <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
        </se:Stroke>
      </se:PolygonSymbolizer>
    </se:Rule>
    <se:Rule>
      <se:Name></se:Name>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>type</ogc:PropertyName>
          <ogc:Literal>condition2</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <se:PolygonSymbolizer>
        <se:Fill>
          <se:SvgParameter name="fill">#fdeb7f</se:SvgParameter>
        </se:Fill>
        <se:Stroke>
          <se:SvgParameter name="stroke">#000000</se:SvgParameter>
          <se:SvgParameter name="stroke-opacity">0.00</se:SvgParameter>
          <se:SvgParameter name="stroke-width">0.26</se:SvgParameter>
          <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
        </se:Stroke>
      </se:PolygonSymbolizer>
    </se:Rule>
    ...condition3, condition4

And then your last rule should contain PropertyIsNotEqualTo all your conditions listed above:

<se:Rule>
      <se:Name></se:Name>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:And>
          <ogc:And>
            <ogc:And>
              <ogc:PropertyIsNotEqualTo>
                <ogc:PropertyName>type</ogc:PropertyName>
                <ogc:Literal>condition1</ogc:Literal>
              </ogc:PropertyIsNotEqualTo>
              <ogc:PropertyIsNotEqualTo>
                <ogc:PropertyName>type</ogc:PropertyName>
                <ogc:Literal>condition2</ogc:Literal>
              </ogc:PropertyIsNotEqualTo>
            </ogc:And>
            <ogc:PropertyIsNotEqualTo>
              <ogc:PropertyName>type</ogc:PropertyName>
              <ogc:Literal>condition3</ogc:Literal>
            </ogc:PropertyIsNotEqualTo>
              </ogc:And>
              <ogc:PropertyIsNotEqualTo>
            <ogc:PropertyName>type</ogc:PropertyName>
            <ogc:Literal>condition4</ogc:Literal>
          </ogc:PropertyIsNotEqualTo>
        </ogc:And>
      </ogc:Filter>
      <se:PolygonSymbolizer>
        <se:Fill>
          <se:SvgParameter name="fill">#9dda58</se:SvgParameter>
        </se:Fill>
        <se:Stroke>
          <se:SvgParameter name="stroke">#000000</se:SvgParameter>
          <se:SvgParameter name="stroke-opacity">0.00</se:SvgParameter>
          <se:SvgParameter name="stroke-width">0.26</se:SvgParameter>
          <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
        </se:Stroke>
      </se:PolygonSymbolizer>
    </se:Rule>

The result of this will be (I used my own features to test it):

enter image description here

  • This works. What if I want to style my layer based on different properties, and different values. How do I define which objects are not yet styled - and I have a lot of those conditions? – Drake Zet Jan 25 '16 at 15:32
  • For Example this: gist.github.com/anonymous/a9e2d34da165cc52e7ce How do I use your approach here? – Drake Zet Jan 25 '16 at 15:47
  • Another thing: I do not think that <ogc:PropertyIsEqualTo> <ogc:PropertyName>umisteni</ogc:PropertyName> <ogc:Literal>v chodníku</ogc:Literal> </ogc:PropertyIsEqualTo> styles all of my data. This basically only styles data that have value "v chodníku" in the attribute "umístění" - definitely not all of my data. – Drake Zet Jan 25 '16 at 15:52
  • I have edited my answer in order to give a solution, please see above. I have tried your GitHub example, and QGis styles all the features twice. The first rule doesn't have a filter and is applied to all the features, and then the other rules (with a filter) are applied again to each feature. – Ralu Bur Jan 26 '16 at 10:10
  • First of all thank you for taking your time and trying to solve this problem. Your workaround is fine, however I have to style data with way more conditions I am showing here - and based on more attributes. This definitely is QGIS bug, as geoserver proccesses my sld the way I have meant it to be. ElseFilter should not need any conditions in it specified, it should function as "go through all the rules, if the object you are proccessing right now meets the condition, use the style, if not, continue - and then the <ElseFilter/> basically just styles any object that has not met any condition – Drake Zet Jan 26 '16 at 12:08
3

So, after extensive testing, I have come to a conclusion that this is indeed QGIS bug. I have tested my sld file in QGIS 2.12.3 and in GeoServer. These are my results:

QGIS: enter image description here

using the same sld file in GeoServer: enter image description here

Below is my sld file:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:se="http://www.opengis.net/se">
<NamedLayer>
<se:Name>dopravni_znacky</se:Name>
<UserStyle>
  <se:Name>dopravni_znacky</se:Name>
  <se:FeatureTypeStyle>
    <se:Rule>
      <se:Name>platne_kriterium</se:Name>
      <se:Description>
        <se:Title>platne_kriterium</se:Title>
      </se:Description>
      <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:PropertyIsEqualTo>
          <ogc:PropertyName>ukotveni</ogc:PropertyName>
          <ogc:Literal>sloup VO</ogc:Literal>
        </ogc:PropertyIsEqualTo>
      </ogc:Filter>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:Mark>
            <se:WellKnownName>circle</se:WellKnownName>
            <se:Fill>
              <se:SvgParameter name="fill">#000000</se:SvgParameter>
              <se:SvgParameter name="fill-opacity">0.00</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#ff0000</se:SvgParameter>
              <se:SvgParameter name="stroke-width">2</se:SvgParameter>
            </se:Stroke>
          </se:Mark>
          <se:Size>5</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>
    <se:Rule>
      <se:Name>default</se:Name>
      <se:Description>
        <se:Title>default</se:Title>
      </se:Description>
      <se:ElseFilter/>
      <se:PointSymbolizer>
        <se:Graphic>
          <se:Mark>
            <se:WellKnownName>circle</se:WellKnownName>
            <se:Fill>
              <se:SvgParameter name="fill">#18d300</se:SvgParameter>
            </se:Fill>
            <se:Stroke>
              <se:SvgParameter name="stroke">#000000</se:SvgParameter>
              <se:SvgParameter name="stroke-opacity">0.00</se:SvgParameter>
            </se:Stroke>
          </se:Mark>
          <se:Size>2</se:Size>
        </se:Graphic>
      </se:PointSymbolizer>
    </se:Rule>
  </se:FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

Basically my sld file says that my points should be red circles when they match my first rule, otherwise they should be green dots. GeoServer does what I've specified in my sld file exactly as how I would expected, however QGIS seems to ignore the se:ElseFilter and just renders every feature with second rule regardless (which here you can see as those green dots in the middle of red circles - both rules rendered at the same time)

I will open a ticket and hope that this gets fixed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.