From 6a2e5ffe771831bfa3cfb8482a5aeac62ec469c8 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 30 Aug 2016 14:48:34 +0200 Subject: [PATCH] Added inheritance support to XML material profile deserialization CURA-2108 --- .../XmlMaterialProfile/XmlMaterialProfile.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 77f775ee27..c1db8f8f2f 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -7,8 +7,10 @@ import io import xml.etree.ElementTree as ET import uuid +from UM.Resources import Resources from UM.Logger import Logger from UM.Util import parseBool +from cura.CuraApplication import CuraApplication import UM.Dictionary @@ -246,6 +248,51 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): 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 def deserialize(self, serialized): data = ET.fromstring(serialized) @@ -255,6 +302,11 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): # TODO: Add material verfication 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) for entry in metadata: