Hey.
I am going through the conversion for py2 to py3 for Maya. I have noticed that strings retrieved from from pm.fileInfo() may have been impacted. My guess is that it is related to unicode changes in python. (All of this used to ‘just’ work with python 2.)
Before I do any grunt work reformatting the string from fileInfo I thought I’d ask you all if you had any suggestion.
Sample Code:
import pymel.core as pm
from xml.etree import ElementTree as ET
from xml.dom import minidom
root = ET.Element("root")
doc = ET.SubElement(root, "animations")
joint_attributes = {'node_type':'joints'}
joints = ET.SubElement(doc, 'joint', attrib=joint_attributes)
joint1 = ET.SubElement(joints, 'joint1')
transform1 = ET.SubElement(joint1, 'transform')
ET.SubElement(transform1, "rotate").text = '(1,2,3)'
ET.SubElement(transform1, "translate").text = '(1,2,3)'
ET.SubElement(transform1, "scale").text = '(1,2,3)'
xmlstr = minidom.parseString(ET.tostring(root, encoding='utf-8')).toprettyxml(indent=" ")
print(xmlstr)
print output
<?xml version="1.0" ?>
<root>
<animations>
<joint node_type="joints">
<joint1>
<transform>
<rotate>(1,2,3)</rotate>
<translate>(1,2,3)</translate>
<scale>(1,2,3)</scale>
</transform>
</joint1>
</joint>
</animations>
</root>
I can read this string (xmlstr) into ET
read_string = ET.fromstring(xmlstr)
I then take the string and add it to fileInfo and retrieve it
pm.fileInfo['xml_test'] = xmlstr
xml_test = pm.fileInfo['xml_test']
print(xml_test )
print output
<?xml version=\"1.0\" ?>\n<root>\n <animations>\n <joint node_type=\"joints\">\n <joint1>\n <transform>\n <rotate>(1,2,3)</rotate>\n <translate>(1,2,3)</translate>\n <scale>(1,2,3)</scale>\n </transform>\n </joint1>\n </joint>\n </animations>\n</root>\n
And the string from fileInfo (xml_test) throws an error while with ElementTree
read_string = ET.fromstring(xml_test)
Error:
Error: ParseError: file C:\Program Files\Autodesk\Maya2022\Python37\lib\xml\etree\ElementTree.py line 1315: XML declaration not well-formed: line 1, column 14
I have tried different encoding passes on the string both before and after adding to fileInfo. (As well as set the encoding for the xml to be ‘utf-8’ and ‘unicode’) :
pm.fileInfo['xml_test'] = xmlstr.encode('utf-8')
or
xml_test = (pm.fileInfo['xml_test']).encode('utf-8')
The desired result would be to read the string from fileInfo (xml_test) and have it comply with ElementTrees expectations. The authoritative version of data lives in fileInfo to be consumed by other tools later after it is converted to xml.
Thanks in advance
-jonathan