python - Modifying an XML File - Dividing values -
i looking modify values in xml file dividing them.
i need divide values se:svgparameter[name="stroke-width"] , se:size 3.6. found tutorial on python.org, modifying xml file, doesn’t seem work , couldn’t find similar on here. or point appreciated!
here's example xml, want able output script in folder multiple files , have convert of them.
xml:
<?xml version="1.0" encoding="iso-8859-1"?> <styledlayerdescriptor version="1.1.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 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>qgis_sld_scaleproblem</se:name> <se:description> <se:title>qgis_sld_scaleproblem</se:title> <se:abstract>this sld in pixels, qgis read mm</se:abstract> </se:description> <userstyle> <se:name>qgis_sld_scaleproblem</se:name> <se:featuretypestyle> <se:rule> <se:name>qgis_sld_scaleproblem_line</se:name> <se:linesymbolizer> <se:name>line</se:name> <se:stroke> <se:svgparameter name="stroke">#ff0000</se:svgparameter> <se:svgparameter name="stroke-width">36</se:svgparameter> </se:stroke> </se:linesymbolizer> </se:rule> <se:rule> <se:name>qgis_sld_scaleproblem_point</se:name> <se:pointsymbolizer> <se:name>point</se:name> <se:graphic> <se:mark> <se:wellknownname>circle</se:wellknownname> <se:fill> <se:svgparameter name="fill">#ff0000</se:svgparameter> </se:fill> </se:mark> <se:size>36</se:size> </se:graphic> </se:pointsymbolizer> </se:rule> </se:featuretypestyle> </userstyle> </namedlayer> </styledlayerdescriptor> code:
import xml.etree.elementtree et lxml import etree tree = et.parse('qgis-sld-scaleproblem_line.sld') root = tree.getroot() # check script reading correct file print("sld file", root[0][0].text, "loaded.") # registers namespaces prevent them being filled defaults et.register_namespace('', "http://www.opengis.net/sld") et.register_namespace('ogc', "http://www.opengis.net/ogc") et.register_namespace('xsi', "http://www.w3.org/2001/xmlschema-instance") et.register_namespace('xlink', "http://www.w3.org/1999/xlink") et.register_namespace('schemalocation', "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/styledlayerdescriptor.xsd") et.register_namespace('se', "http://www.opengis.net/se") # section "should" search xml se:svgparameter name="stroke-width" , se:size , divide value 3.6 svgparameter in root.iter('svgparameter'): new_svgparameter = int(svgparameter.text) / 3.6 svgparameter.text = str(new_svgparameter) size in root.iter('size'): new_size= int(size.text) / 3.6 size.text = str(new_size) tree.write("gis-sld-scalefixed.sld", xml_declaration=true, encoding='iso-8859-1') answers i’ve looked at:
consider xslt special-purpose language designed transform xml files. , python's lxml module can run xslt 1.0 scripts. plus xslt can run outside python, hence portability.
simply call identity transform copy whole document , run division on selected nodes. no for loops or if logic needed approach.
xslt (save .xsl file, special well-formed xml file)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:se="http://www.opengis.net/se"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="se:svgparameter[@name='stroke-width']|se:size"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:value-of select="format-number(text(), '#') div 3.6"/> </xsl:copy> </xsl:template> </xsl:stylesheet> python (iterate below process in loop multiple files)
import lxml.etree et # load xml , xsl doc = et.parse('input.xml') xsl = et.parse('xsltscript.xsl') # transform transform = et.xslt(xsl) result = transform(doc) # output screen print(result) # output file open('output.xml', 'wb') f: f.write(result) output
<?xml version="1.0"?> <styledlayerdescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:se="http://www.opengis.net/se" version="1.1.0" xsi:schemalocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/styledlayerdescriptor.xsd"> <namedlayer> <se:name>qgis_sld_scaleproblem</se:name> <se:description> <se:title>qgis_sld_scaleproblem</se:title> <se:abstract>this sld in pixels, qgis read mm</se:abstract> </se:description> <userstyle> <se:name>qgis_sld_scaleproblem</se:name> <se:featuretypestyle> <se:rule> <se:name>qgis_sld_scaleproblem_line</se:name> <se:linesymbolizer> <se:name>line</se:name> <se:stroke> <se:svgparameter name="stroke">#ff0000</se:svgparameter> <se:svgparameter name="stroke-width">10</se:svgparameter> </se:stroke> </se:linesymbolizer> </se:rule> <se:rule> <se:name>qgis_sld_scaleproblem_point</se:name> <se:pointsymbolizer> <se:name>point</se:name> <se:graphic> <se:mark> <se:wellknownname>circle</se:wellknownname> <se:fill> <se:svgparameter name="fill">#ff0000</se:svgparameter> </se:fill> </se:mark> <se:size>10</se:size> </se:graphic> </se:pointsymbolizer> </se:rule> </se:featuretypestyle> </userstyle> </namedlayer> </styledlayerdescriptor>
Comments
Post a Comment