Added inheritance support to XML material profile deserialization

CURA-2108
This commit is contained in:
Jaime van Kessel 2016-08-30 14:48:34 +02:00
parent 91c11ee0fc
commit 6a2e5ffe77

View file

@ -7,8 +7,10 @@ import io
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import uuid import uuid
from UM.Resources import Resources
from UM.Logger import Logger from UM.Logger import Logger
from UM.Util import parseBool from UM.Util import parseBool
from cura.CuraApplication import CuraApplication
import UM.Dictionary import UM.Dictionary
@ -246,6 +248,51 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
return stream.getvalue() return stream.getvalue()
# Recursively resolve loading inherited files
def _resolveInheritance(self, file_name):
xml = self._loadFile(file_name)
inherits = xml.find("./um:inherits", self.__namespaces)
if inherits is not None:
inherited = self._resolveInheritance(inherits.text)
xml = self._mergeXML(inherited, xml)
return xml
def _loadFile(self, file_name):
path = Resources.getPath(CuraApplication.getInstance().ResourceTypes.MaterialInstanceContainer, file_name + ".xml.fdm_material")
contents = {}
with open(path, encoding="utf-8") as f:
contents = f.read()
#self._inherited_files.append(path)
return ET.fromstring(contents)
def _mergeXML(self, first, second):
result = copy.deepcopy(first)
self._combineElement(result, second)
return result
# Recursively merges XML elements. Updates either the text or children if another element is found in first.
# If it does not exist, copies it from second.
def _combineElement(self, first, second):
# Create a mapping from tag name to element.
mapping = {el.tag: el for el in first}
for el in second:
if len(el): # Check if element has children.
try:
self._combineElement(mapping[el.tag], el) # Multiple elements, handle those.
except KeyError:
mapping[el.tag] = el
first.append(el)
else:
try:
mapping[el.tag].text = el.text
except KeyError: # Not in the mapping, so simply add it
mapping[el.tag] = el
first.append(el)
## Overridden from InstanceContainer ## Overridden from InstanceContainer
def deserialize(self, serialized): def deserialize(self, serialized):
data = ET.fromstring(serialized) data = ET.fromstring(serialized)
@ -255,6 +302,11 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
# TODO: Add material verfication # TODO: Add material verfication
self.addMetaDataEntry("status", "unknown") self.addMetaDataEntry("status", "unknown")
#for inherit in data.findall("./um:inherits", self.__namespaces):
inherits = data.find("./um:inherits", self.__namespaces)
if inherits is not None:
inherited = self._resolveInheritance(inherits.text)
data = self._mergeXML(inherited, data)
metadata = data.iterfind("./um:metadata/*", self.__namespaces) metadata = data.iterfind("./um:metadata/*", self.__namespaces)
for entry in metadata: for entry in metadata: