0

The idea is to create a style that will define different styles for certain groups of polygons using the element, and for all other polygons for which no style has been defined, generate a special style using .

Polygons are displayed on the map at a scale of 1:250000.

This part works correctly, but there is a problem when I add the label. The label must be displayed for ALL polygons on a scale of 1:5000.

At a scale of 1:5000, the polygons for which the style is defined in are no longer displayed on the map. Polygons that are defined in the block are correctly displayed with labels.

It seems like the style defined in overrides the style defined in

1:10000

enter image description here

1: 5000

enter image description here

Here is my code:

<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0" 
                   xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" 
                   xmlns="http://www.opengis.net/sld" 
                   xmlns:ogc="http://www.opengis.net/ogc" 
                   xmlns:xlink="http://www.w3.org/1999/xlink" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
  <Name>Test</Name>
  <UserStyle>
  <Title>Test</Title>
  <FeatureTypeStyle>

    <Rule>
      <Title>Group 1</Title>
      <MaxScaleDenominator>250000</MaxScaleDenominator>
      <ogc:Filter>
        <PropertyIsEqualTo>
          <PropertyName>attr1</PropertyName>
          <Literal>1</Literal>
        </PropertyIsEqualTo>
      </ogc:Filter>
      <PolygonSymbolizer>
        <Fill>
          <CssParameter name="fill">#99e6ff</CssParameter>
          <CssParameter name="fill-opacity">0.6</CssParameter>
        </Fill>
        <Stroke>
          <CssParameter name="stroke">#0086b3</CssParameter>
          <CssParameter name="stroke-width">1</CssParameter>
        </Stroke>
      </PolygonSymbolizer>
    </Rule>


    <Rule>
      <Title>Group 2</Title>
      <MaxScaleDenominator>250000</MaxScaleDenominator>
      <ogc:Filter>
        <PropertyIsEqualTo>
          <PropertyName>attr2</PropertyName>
          <Literal>2</Literal>
        </PropertyIsEqualTo>
      </ogc:Filter>
      <PolygonSymbolizer>
        <Fill>
          <CssParameter name="fill">#71da71</CssParameter>
          <CssParameter name="fill-opacity">0.6</CssParameter>
        </Fill>
        <Stroke>
          <CssParameter name="stroke">#258e25</CssParameter>
          <CssParameter name="stroke-width">1</CssParameter>
        </Stroke>
      </PolygonSymbolizer>
    </Rule>
    

    <Rule>
      <Title>Group undefined</Title>
      <MaxScaleDenominator>250000</MaxScaleDenominator>
      <ogc:ElseFilter/>   
      <PolygonSymbolizer>
        <Fill>
          <GraphicFill>
            <Graphic>
              <Mark>
                <WellKnownName>shape://times</WellKnownName>
                <Stroke>
                  <CssParameter name="stroke">#eb4034</CssParameter>
                  <CssParameter name="stroke-width">2</CssParameter>
                </Stroke>
              </Mark>
              <Size>10</Size>
            </Graphic>
          </GraphicFill>
        </Fill>
        <Stroke>
          <CssParameter name="stroke">#eb4034</CssParameter>
          <CssParameter name="stroke-width">1</CssParameter>
        </Stroke>
      </PolygonSymbolizer>
    </Rule>

    
    <Rule>
      <MaxScaleDenominator>5000</MaxScaleDenominator>
      <TextSymbolizer>
        <Label>
          <ogc:PropertyName>attr_label</ogc:PropertyName>
        </Label>
        <Font>
          <CssParameter name="font-family">arial</CssParameter>
          <CssParameter name="font-weight">Bold</CssParameter>
          <CssParameter name="font-size">10</CssParameter>
        </Font>
        <LabelPlacement>
          <PointPlacement>
            <AnchorPoint>
              <AnchorPointX>0.5</AnchorPointX>
              <AnchorPointY>0.5</AnchorPointY>
            </AnchorPoint>
            <Displacement>
              <DisplacementX>0</DisplacementX>
              <DisplacementY>0</DisplacementY>
            </Displacement>
          </PointPlacement>
        </LabelPlacement>
        <Fill>
          <CssParameter name="fill">#000000</CssParameter>
        </Fill>
      </TextSymbolizer>
    </Rule>


  </FeatureTypeStyle>
</UserStyle>

What am I doing wrong?

1 Answer 1

1

It appears the ElseFilter is in the sld or se namespace, not ogc (like Filter), so try <ElseFilter> instead of <ogc:ElseFilter>

Sources:

https://sourceforge.net/p/geoserver/mailman/message/26528124/

https://schemas.opengis.net/se/1.1.0/FeatureStyle.xsd

EDIT:

Looking at this answer, https://gis.stackexchange.com/a/178088/206101 A work around might be to replace the ElseFilter with a Filter for And PropertyIsNotEqualTo, e.g.something like:

<ogc:Filter>
   <ogc:And>
      <ogc:PropertyIsNotEqualTo>
          <ogc:PropertyName>attr1</ogc:PropertyName>
          <ogc:Literal>1</ogc:Literal>
      </ogc:PropertyIsNotEqualTo>
      <ogc:PropertyIsNotEqualTo>
          <ogc:PropertyName>attr2</ogc:PropertyName>
          <ogc:Literal>2</ogc:Literal>
      </ogc:PropertyIsNotEqualTo>
   </ogc:And>
</ogc:Filter>

Otherwise, I think the TextSymbolizer's Filter is in fact overwriting the ElseFilter (by design of how ElseFilter works). If you really need to use an ElseFilter I think the only other solution would be to separate the Polygon rules and TextSymbolizer rule into separate styles

EDIT 2: Also, you may also need to use <se:ElseFilter> and add xmlns:se="http://www.opengis.net/se" to <StyledLayerDescriptor>

EDIT 3: Regarding how ElseFilters work, the Symbology Encoding spec says:

The ElseFilter allows rules to be specified that are activated for features that are not selected by any other rule in a feature-type style. [...] The nominal scale of the map to be portrayed is computed (as described in the previous subclause) and all rules for scale ranges that do not include the computed nominal scale are discarded from further processing. [...] A simple optimization for the above procedure is that if any rules of a user style have no Filter condition (i.e., are always “true”), then any ElseFilter rules can simply be discarded, since their selection condition will always be false.

Or from the Mapnik documentation in the linked answer:

A Rule containing an <ElseFilter /> is evaluated if and only if no other Rule in the current Style matched (either because of the ScaleDenominator or the Filter).

3
  • The behavior is the same in both cases
    – ncica
    Nov 11, 2022 at 0:03
  • @ncica, edited my answer to provide other possible solutions
    – John
    Nov 11, 2022 at 0:18
  • I'm not sure what the expected behaviour is when you have an else filter and an unfiltered rule. The spec may clarify otherwise you will need to check the code.
    – Ian Turton
    Nov 11, 2022 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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