3

I am trying to style my WMS map using sld_body parameter as explained in GeoServer working with SLD docs. I tested with simple SLD file as below,

var sld = `<?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>default_polygon</Name>
      <UserStyle>
        <Title>Default Polygon</Title>
        <Abstract>A sample style that draws a polygon</Abstract>
        <FeatureTypeStyle>
          <Rule>
            <Name>rule1</Name>
            <Title>Gray Polygon with Black Outline</Title>
            <Abstract>A polygon with a gray fill and a 1 pixel black outline</Abstract>
            <PolygonSymbolizer>
              <Fill>
                <CssParameter name="fill">#AAAAAA</CssParameter>
              </Fill>
              <Stroke>
                <CssParameter name="stroke">#000000</CssParameter>
                <CssParameter name="stroke-width">1</CssParameter>
              </Stroke>
            </PolygonSymbolizer>
          </Rule>
        </FeatureTypeStyle>
      </UserStyle>
    </NamedLayer>
  </StyledLayerDescriptor>
  `;

Then I tried to add the style as below,

var layer = L.tileLayer.wms(
    "http://localhost:8080/geoserver/wms/reflect?sld_body=" + sld,
    {
      layers: "topp:layer_name",
      format: "image/png",
      styles: "",
      transparent: true,
      attribution: "mylayer",
    }
  );

Now I can't access my WMS layer. In geoserver log file, it shows the XML error as below,

Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 
814; XML document structures must start and end within the same entity.                                                                                                          
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)                                           
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)                                    
at org.geotools.xml.styling.SLDParser.parseSLD(SLDParser.java:470)                                                      
... 122 more 

In GeoServer docs, it explains The SLD XML must be URL-encoded. So I tried to encode this SLD using encodeURI as below,

sld = encodeURI(sld)

var layer = L.tileLayer.wms(
    "http://localhost:8080/geoserver/wms/reflect?sld_body=" + sld,
    {
      layers: "topp:layer_name",
      format: "image/png",
      styles: "",
      transparent: true,
      attribution: "mylayer",
    }
  );

The layer is still not visible. I checked the GeoServer log and found this error,

Caused by: org.xml.sax.SAXParseException; lineNumber: 20; columnNumber: 43; 
XML document structures must start and end within the same entity.                                                                                                          
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)                                           
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)                                    
at org.geotools.xml.styling.SLDParser.parseSLD(SLDParser.java:470)                                                      
... 122 more      

I verified that the same SLD is working when I uploaded it to the GeoServer.

1
4

Let me quote the Leaflet API reference about L.TileLayer.WMS:

If any custom options not documented here are used, they will be sent to the WMS server as extra parameters in each request URL. This can be useful for non-standard vendor WMS parameters.

Thus, instead of ...

var layer = L.tileLayer.wms(
  "http://localhost:8080/geoserver/wms/reflect?sld_body=" + sld,
  {
    layers: "topp:layer_name",
    // ...etc

... you should do something like ...

var layer = L.tileLayer.wms(
  "http://localhost:8080/geoserver/wms/reflect?",
  {
    layers: "topp:layer_name",
    sld_body: sld,
    // ...etc

...this way, Leaflet will internally apply encodeURIComponent (and not encodeURI) to all the extra parameters.

Note that the outputs of encodeURIComponent(sld) and encodeURI(sld) are different.

1
  • Great!!! This solution worked. Also, I added the <IsDefault>1</IsDefault> inside UserStyle node in my sld. Now it is working fine. Thank you very much. – dhiraj Apr 9 at 2:05

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.