4

The name of the sole layer in the draft ArcGIS map myfile.mxd is Mächtigkeit which contains the German umlaut ä. I face an error message when using the script mxd2qgs.py (downloaded from https://github.com/fitnr/mxd2qgs) although some workarounds are implemented. The script mxd2qgs_short.py below is, to my point, the most possible reduction of the original script, still producing the error.

It looks like the error occurs from interaction of the two sections Section mapcanvas and Section legend with each other. Turning off Section mapcanvas makes the error message disappear. I don't manage to trace the interaction of the layer name with Section mapcanvas. How should I proceed in mxd2qgs_short.py to handle this problem?

Using doc.toprettyxml() is suggested here.

Script mxd2qgs_short.py:

from xml.dom.minidom import Document
import arcpy

mxd = arcpy.mapping.MapDocument(r"myfile.mxd")
qgs = 'myfile.qgs'

df = arcpy.mapping.ListDataFrames(mxd)[0]
lyrlist = arcpy.mapping.ListLayers(df)
lyr, = lyrlist

doc = Document()
qgis = doc.createElement("qgis")
doc.appendChild(qgis)
legend = doc.createElement("legend")
qgis.appendChild(legend)
unit = doc.createTextNode(df.mapUnits)
units = doc.createElement("units")
units.appendChild(unit)

# Section mapcanvas
mapcanvas = doc.createElement("mapcanvas")
qgis.appendChild(mapcanvas)
mapcanvas.appendChild(units)

# Section legend
legendlayer = doc.createElement("legendlayer")
legendlayer.setAttribute("name",lyr.name.encode('iso-8859-1'))
legend.appendChild(legendlayer)

f = open(qgs,"w")
f.write(doc.toprettyxml())
f.close()

Error message:

Traceback (most recent call last):
  File "D:\mxd2qgs_short.py", line 31, in <module>
    f.write(doc.toprettyxml())
  File "C:\Python27\ArcGIS10.5\lib\xml\dom\minidom.py", line 61, in toprettyxml
    return writer.getvalue()
  File "C:\Python27\ArcGIS10.5\lib\StringIO.py", line 271, in getvalue
    self.buf += ''.join(self.buflist)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 1: ordinal not in range(128)
3

In the comments of Python's StringIO.py's getvalue, it was noted that if the data source for the IO object contained both unicode and 8-bit strings, with any of the latter containing 8-bit but non-ASCII characters (like ä encoded in iso-8859-1), UnicodeDecodeErrors could result. Since you've found commenting out the mapcanvas section avoids error, and the units element is a child of that element in your structure, I would check the value of df.mapUnits, as that is more data directly out of ArcPy and I suspect that it uses unicode strings universally. While you've encoded the layer name in a format for 8-bit string characters, if df.mapUnits is also a unicode string - even if it doesn't contain any non-ASCII characters - the error you're seeing might occur (it did when I attempted to replicate it). To fix it if that is the case, you can encode df.mapUnits as well in the same encoding, e.g.:

unit = doc.createTextNode(df.mapUnits.encode('iso-8859-1'))

In general, you'll probably want to make sure you apply your choice of output encoding consistently across any strings you're getting from ArcPy (in the code sample that's just lyr.name and df.mapUnits, but if the broader script contains other string values straight from ArcPy then encode those too).

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.