def test_set_attribute_with_qname_key(self, mock_to_xml): key = QName("foo", "bar") SerializeUtils.set_attribute(self.element, key, "value", self.namespaces) self.assertEqual("val", self.element.attrib[key]) self.assertEqual({"ns0": "foo"}, self.namespaces.ns_map) mock_to_xml.assert_called_once_with("value", self.namespaces)
def test_set_attributes(self, mock_set_attribute): values = dict(a=1, b=2) SerializeUtils.set_attributes(self.element, values, self.namespaces) mock_set_attribute.assert_has_calls([ mock.call(self.element, "a", 1, self.namespaces), mock.call(self.element, "b", 2, self.namespaces), ])
def render_sub_node(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): if isinstance(value, AnyElement): self.render_wildcard_node(parent, value, var, namespaces) elif var.is_element or is_dataclass(value): self.render_element_node(parent, value, var, namespaces) elif not parent.text: SerializeUtils.set_text(parent, value, namespaces) else: SerializeUtils.set_tail(parent, value, namespaces)
def render_element_node(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): qname = value.qname if hasattr(value, "qname") else var.qname if isinstance(qname, QName): namespaces.add(qname.namespace) sub_element = SubElement(parent, qname) self.render_node(sub_element, value, namespaces) self.set_xsi_type(sub_element, value, var, namespaces) SerializeUtils.set_nil_attribute(sub_element, var.nillable, namespaces)
def set_xsi_type(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): if not var.clazz or value.__class__ is var.clazz: return if self.context.is_derived(value, var.clazz): meta = self.context.fetch(value.__class__, QName(parent.tag).namespace) SerializeUtils.set_attribute(parent, QNames.XSI_TYPE, meta.source_qname, namespaces) else: raise SerializerError( f"{value.__class__.__name__} is not derived from {var.clazz.__name__}" )
def render_element_node(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): """Render a child element for the given parent according to the field xml metadata.""" if hasattr(value, "qname"): qname = value.qname elif var.is_wildcard: meta = self.context.fetch(value.__class__, QName(parent).namespace) qname = meta.qname else: qname = var.qname namespaces.add(qname.namespace) sub_element = SubElement(parent, qname) self.render_node(sub_element, value, namespaces) self.set_xsi_type(sub_element, value, var, namespaces) SerializeUtils.set_nil_attribute(sub_element, var.nillable, namespaces)
def render_wildcard_node(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): if value.qname: sub_element = SubElement(parent, value.qname) else: sub_element = parent namespaces.add_all(value.ns_map) SerializeUtils.set_text(sub_element, value.text, namespaces) SerializeUtils.set_tail(sub_element, value.tail, namespaces) SerializeUtils.set_attributes(sub_element, value.attributes, namespaces) for child in value.children: self.render_sub_node(sub_element, child, var, namespaces) SerializeUtils.set_nil_attribute(sub_element, var.nillable, namespaces)
def test_set_nil_attribute(self): SerializeUtils.set_nil_attribute(self.element, False, self.namespaces) self.assertNotIn(QNames.XSI_NIL, self.element.attrib) self.element.text = "foo" SerializeUtils.set_nil_attribute(self.element, True, self.namespaces) self.assertNotIn(QNames.XSI_NIL, self.element.attrib) self.element.text = None sub_element = SubElement(self.element, "foo") SerializeUtils.set_nil_attribute(self.element, True, self.namespaces) self.assertNotIn(QNames.XSI_NIL, self.element.attrib) self.element.remove(sub_element) SerializeUtils.set_nil_attribute(self.element, True, self.namespaces) self.assertEqual("true", self.element.attrib[QNames.XSI_NIL])
def render_wildcard_node(self, parent: Element, value: Any, var: XmlVar, namespaces: Namespaces): """Render a child element for the given parent according to the wildcard field metadata.""" if value.qname: sub_element = SubElement(parent, value.qname) else: sub_element = parent namespaces.add_all(value.ns_map) SerializeUtils.set_text(sub_element, value.text, namespaces) SerializeUtils.set_tail(sub_element, value.tail, namespaces) SerializeUtils.set_attributes(sub_element, value.attributes, namespaces) for child in value.children: self.render_sub_node(sub_element, child, var, namespaces) SerializeUtils.set_nil_attribute(sub_element, var.nillable, namespaces)
def render_complex_node(self, parent: Element, obj: Any, namespaces: Namespaces): meta = self.context.build(obj.__class__, QName(parent).namespace) for var, value in self.next_value(meta, obj): if value is None: continue elif var.is_attribute: SerializeUtils.set_attribute(parent, var.qname, value, namespaces) elif var.is_attributes: SerializeUtils.set_attributes(parent, value, namespaces) elif var.is_text: namespaces.add(var.qname.namespace) SerializeUtils.set_text(parent, value, namespaces) elif isinstance(value, list): self.render_sub_nodes(parent, value, var, namespaces) else: self.render_sub_node(parent, value, var, namespaces) SerializeUtils.set_nil_attribute(parent, meta.nillable, namespaces)
def render_node(self, parent: Element, obj: Any, namespaces: Namespaces): """Recursively traverse the given object and build the xml tree.""" if is_dataclass(obj): self.render_complex_node(parent, obj, namespaces) else: SerializeUtils.set_text(parent, obj, namespaces)
def test_set_tail(self): SerializeUtils.set_tail(self.element, 1, self.namespaces) self.assertEqual("1", self.element.tail) SerializeUtils.set_tail(self.element, "", self.namespaces) self.assertIsNone(self.element.tail)
def test_set_attribute_with_qname_xsi_nil_and_element_has_children(self): SubElement(self.element, "bar") SerializeUtils.set_attribute(self.element, QNames.XSI_NIL, True, self.namespaces) self.assertNotIn(QNames.XSI_NIL, self.element.attrib)
def test_set_attribute_with_qname_xsi_nil_and_element_has_text(self): self.element.text = "foo" SerializeUtils.set_attribute(self.element, QNames.XSI_NIL, True, self.namespaces) self.assertNotIn(QNames.XSI_NIL, self.element.attrib)
def test_set_attribute_with_qname_xsi_nil(self): SerializeUtils.set_attribute(self.element, QNames.XSI_NIL, True, self.namespaces) self.assertEqual("true", self.element.attrib[QNames.XSI_NIL])
def test_set_attribute_when_value_empty(self, mock_to_xml): SerializeUtils.set_attribute(self.element, "key", "value", self.namespaces) self.assertNotIn("key", self.element.attrib) self.assertEqual(0, len(self.namespaces.ns_map)) mock_to_xml.assert_called_once_with("value", self.namespaces)