def createAndParseSld(qgisLayerItem): document = QDomDocument() header = document.createProcessingInstruction( 'xml', 'version=\'1.0\' encoding=\'UTF-8\'') document.appendChild(header) root = document.createElementNS('http://www.opengis.net/sld', 'StyledLayerDescriptor') root.setAttribute('version', '1.0.0') root.setAttribute('xmlns:ogc', 'http://www.opengis.net/ogc') root.setAttribute('xmlns:sld', 'http://www.opengis.net/sld') root.setAttribute('xmlns:gml', 'http://www.opengis.net/gml') document.appendChild(root) namedLayerNode = document.createElement('sld:NamedLayer') root.appendChild(namedLayerNode) qgisLayerItem.layer.writeSld(namedLayerNode, document, '') nameNode = namedLayerNode.firstChildElement('se:Name') oldNameText = nameNode.firstChild() newname = qgisLayerItem.parentShogunLayer.source['layerNames'] newNameText = document.createTextNode(newname) nameNode.appendChild(newNameText) nameNode.removeChild(oldNameText) userStyleNode = namedLayerNode.firstChildElement('UserStyle') userStyleNameNode = userStyleNode.firstChildElement('se:Name') userStyleNameText = userStyleNameNode.firstChild() userStyleNameNode.removeChild(userStyleNameText) userStyleNameNode.appendChild( document.createTextNode(qgisLayerItem.stylename)) titleNode = document.createElement('sld:Title') title = document.createTextNode('A QGIS-Style for ' + qgisLayerItem.layer.name()) titleNode.appendChild(title) userStyleNode.appendChild(titleNode) defaultNode = document.createElement('sld:IsDefault') defaultNode.appendChild(document.createTextNode('1')) userStyleNode.appendChild(defaultNode) featureTypeStyleNode = userStyleNode.firstChildElement( 'se:FeatureTypeStyle') featureTypeStyleNameNode = document.createElement('sld:Name') featureTypeStyleNameNode.appendChild(document.createTextNode('name')) featureTypeStyleNode.appendChild(featureTypeStyleNameNode) rules = featureTypeStyleNode.elementsByTagName('se:Rule') for x in range(rules.length()): rule = rules.at(x) rule.removeChild(rule.firstChildElement('se:Description')) # Check if custom icons are used in symbology and replace the text: # search if tag 'se:OnlineResource' is in the sld document listOfGraphics = rule.toElement().elementsByTagName('se:OnlineResource') if not listOfGraphics.isEmpty(): for x in range(listOfGraphics.length()): graphicNode = listOfGraphics.at(x) currentIcon = graphicNode.attributes().namedItem( 'xlink:href').nodeValue() iconUrl = qgisLayerItem.ressource.prepareIconForUpload(currentIcon) graphicNode.toElement().setAttribute('xlink:href', iconUrl) graphicNode.toElement().setAttribute( 'xmlns:xlink', 'http://www.w3.org/1999/xlink') sld = document.toString() # in qgis3 layer.writeSld() also incluedes labeling in the output sld, # whereas in qgis2 we have to do this manually by using this module's function # getLabelingAsSld ## TODO: The automatic sld labeling from QGIS 3 produces an extra rule for # every labeling style, thus leading to a less beautiful viewe in the # shogun2-webapp styler - is this a problem? if qgisLayerItem.layer.labelsEnabled() and PYTHON_VERSION < 3: labelSld = getLabelingAsSld(qgisLayerItem.layer) sld = sld.replace('</se:Rule>', labelSld + '</se:Rule>') sld = sld.replace('ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"', 'ogc:Filter') # the following fixes weird problems with the sld compability with the # shogun webapp sld = sld.replace('<ogc:And>', '') sld = sld.replace('</ogc:And>', '') sld = sld.replace('<se:Name> ', '<se:Name>') sld = sld.replace(' </se:Name>', '</se:Name>') sld = sld.replace('StyledLayerDescriptor', 'sld:StyledLayerDescriptor') sld = sld.replace('UserStyle', 'sld:UserStyle') sld = sld.replace('se:', 'sld:') sld = sld.replace('SvgParameter', 'CssParameter') sld = sld.replace('\n', '') sld = sld.replace('\t', '') return sld
def getStyleAsSld(layer, styleName): if layer.type() == layer.VectorLayer: document = QDomDocument() header = document.createProcessingInstruction("xml", "version=\"1.0\"") document.appendChild(header) root = document.createElementNS("http://www.opengis.net/sld", "StyledLayerDescriptor") root.setAttribute("version", "1.0.0") root.setAttribute("xmlns:ogc", "http://www.opengis.net/ogc") root.setAttribute("xmlns:sld", "http://www.opengis.net/sld") # root.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink" ) # root.setAttribute( # "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ) document.appendChild(root) namedLayerNode = document.createElement("sld:NamedLayer") root.appendChild(namedLayerNode) nameNode = document.createElement("sld:Name") featureTypeStyleElem = document.createElement("sld:FeatureTypeStyle") namedLayerNode.appendChild(nameNode) nameNode.appendChild(document.createTextNode(styleName)) userNode = document.createElement("sld:UserStyle") namedLayerNode.appendChild(userNode) nameElem = document.createElement("sld:Name") nameElem.appendChild(document.createTextNode(styleName)) userNode.appendChild(nameElem) titleElem = document.createElement("sld:Title") titleElem.appendChild(document.createTextNode(styleName)) userNode.appendChild(titleElem) rule = layer.renderer().rootRule() props = {} # QgsStringMap() can be see as a python dictionary rule_to_sld(rule, document, featureTypeStyleElem, props) userNode.appendChild(featureTypeStyleElem) return str(document.toString(4)) elif layer.type() == layer.RasterLayer: renderer = layer.renderer() if isinstance(renderer, QgsSingleBandGrayRenderer): symbolizerCode = "<Opacity>%d</Opacity>" % renderer.opacity() symbolizerCode += ( "<ChannelSelection><GrayChannel><SourceChannelName>" + str(renderer.grayBand()) + "</SourceChannelName></GrayChannel></ChannelSelection>") sld = RASTER_SLD_TEMPLATE.replace("SYMBOLIZER_CODE", symbolizerCode).replace( "STYLE_NAME", layer.name()) return sld elif isinstance(renderer, QgsSingleBandPseudoColorRenderer): symbolizerCode = "<ColorMap>" # band = renderer.usesBands()[0] items = \ renderer.shader().rasterShaderFunction().colorRampItemList() for item in items: color = item.color rgb = '#%02x%02x%02x' % (color.red(), color.green(), color.blue()) symbolizerCode += ('<ColorMapEntry color="' + rgb + '" quantity="' + str(item.value) + '" />') symbolizerCode += "</ColorMap>" sld = RASTER_SLD_TEMPLATE.replace("SYMBOLIZER_CODE", symbolizerCode).replace( "STYLE_NAME", layer.name()) return sld else: # we use some default styles in case we have an # unsupported renderer sldpath = os.path.join(os.path.dirname(__file__), "..", "resources") if layer.bandCount() == 1: sldfile = os.path.join(sldpath, "grayscale.sld") else: sldfile = os.path.join(sldpath, "rgb.sld") with open(sldfile, 'r', newline='') as f: sld = f.read() return sld else: return None