def save(self, output=None, options=None): self.options = options or {} output = self.open_out_stream(output) self.prefixes.clear() self.reverse_nsmap.clear() serialize_default = \ self.options.get(XMIOptions.SERIALIZE_DEFAULT_VALUES, False) nsmap = {XMI: XMI_URL, XSI: XSI_URL} if len(self.contents) == 1: root = self.contents[0] self.register_eobject_epackage(root) tmp_xmi_root = self._go_across(root, serialize_default) else: tag = etree.QName(XMI_URL, 'XMI') tmp_xmi_root = etree.Element(tag) for root in self.contents: root_node = self._go_across(root, serialize_default) tmp_xmi_root.append(root_node) # update nsmap with prefixes register during the nodes creation nsmap.update(self.prefixes) xmi_root = etree.Element(tmp_xmi_root.tag, nsmap=nsmap) xmi_root[:] = tmp_xmi_root[:] xmi_root.attrib.update(tmp_xmi_root.attrib) xmi_version = etree.QName(XMI_URL, 'version') xmi_root.attrib[xmi_version] = '2.0' tree = etree.ElementTree(xmi_root) tree.write(output, pretty_print=True, xml_declaration=True, encoding=tree.docinfo.encoding) self.uri.close_stream()
def _add_explicit_type(self, node, obj): xsi_type = etree.QName(self.xsi_type_url(), 'type') uri = obj.eClass.ePackage.nsURI if uri not in self.reverse_nsmap: epackage = self.get_metamodel(uri) self.register_nsmap(epackage.nsPrefix, uri) prefix = self.reverse_nsmap[uri] node.attrib[xsi_type] = '{0}:{1}'.format(prefix, obj.eClass.name)
def extract_namespace(tag): qname = etree.QName(tag) return qname.namespace, qname.localname
def _go_across(self, obj, serialize_default=False): self.register_eobject_epackage(obj) eclass = obj.eClass if not obj.eContainmentFeature(): # obj is the root epackage = eclass.ePackage nsURI = epackage.nsURI tag = etree.QName(nsURI, eclass.name) if nsURI else eclass.name node = etree.Element(tag) else: node = etree.Element(obj.eContainmentFeature().name) if obj.eContainmentFeature().eType != eclass: self._add_explicit_type(node, obj) if self.use_uuid: self._assign_uuid(obj) xmi_id = '{{{0}}}id'.format(XMI_URL) node.attrib[xmi_id] = obj._internal_id for feat in obj._isset: if feat.derived or feat.transient: continue feat_name = feat.name value = obj.__getattribute__(feat_name) if hasattr(feat.eType, 'eType') and feat.eType.eType is dict: for key, val in value.items(): entry = etree.Element(feat_name) entry.attrib['key'] = key entry.attrib['value'] = val node.append(entry) elif isinstance(feat, Ecore.EAttribute): etype = feat.eType if feat.many and value: to_str = etype.to_string has_special_char = False result_list = [] for v in value: string = to_str(v) if any(x.isspace() for x in string): has_special_char = True result_list.append(string) if has_special_char: for v in result_list: sub = etree.SubElement(node, feat_name) sub.text = v else: node.attrib[feat_name] = ' '.join(result_list) continue default_value = feat.get_default_value() if value != default_value or serialize_default: if value is None: node.append(self._build_none_node(feat_name)) else: node.attrib[feat_name] = etype.to_string(value) continue elif isinstance(feat, Ecore.EReference) and \ feat.eOpposite and feat.eOpposite.containment: continue elif isinstance(feat, Ecore.EReference) \ and not feat.containment: if not value: if serialize_default and value is None: node.append(self._build_none_node(feat_name)) continue if feat.many: results = [self._build_path_from(x) for x in value] embedded = [] crossref = [] for i, result in enumerate(results): frag, cref = result if cref: crossref.append((i, frag)) else: embedded.append(frag) if embedded: result = ' '.join(embedded) node.attrib[feat_name] = result for i, ref in crossref: sub = etree.SubElement(node, feat_name) sub.attrib['href'] = ref self._add_explicit_type(sub, value[i]) else: frag, is_crossref = self._build_path_from(value) if is_crossref: sub = etree.SubElement(node, feat_name) sub.attrib['href'] = frag self._add_explicit_type(sub, value) else: node.attrib[feat_name] = frag if isinstance(feat, Ecore.EReference) and feat.containment: children = obj.__getattribute__(feat_name) children = children if feat.many else [children] for child in children: node.append(self._go_across(child, serialize_default)) return node
def _build_none_node(self, feature_name): sub = etree.Element(feature_name) xsi_null = etree.QName(self.xsi_type_url(), 'nil') sub.attrib[xsi_null] = 'true' return sub