def test_serialize(self): from spyne.util.xml import get_object_as_xml from lxml import etree class C(ComplexModel): __namespace__ = "tns" i = Integer s = Unicode c = C(i=5, s="x") ret = get_object_as_xml(c, C) print etree.tostring(ret) assert ret.tag == "{tns}C" ret = get_object_as_xml(c, C, "X") print etree.tostring(ret) assert ret.tag == "{tns}X" ret = get_object_as_xml(c, C, "X", no_namespace=True) print etree.tostring(ret) assert ret.tag == "X" ret = get_object_as_xml(c, C, no_namespace=True) print etree.tostring(ret) assert ret.tag == "C"
def test_serialize(self): from spyne.util.xml import get_object_as_xml from lxml import etree class C(ComplexModel): __namespace__ = "tns" i = Integer s = Unicode c = C(i=5, s="x") ret = get_object_as_xml(c, C) print etree.tostring(ret) assert ret.tag == "{tns}C" ret = get_object_as_xml(c, C, "X") print etree.tostring(ret) assert ret.tag == "{tns}X" ret = get_object_as_xml(c, C, "X", no_namespace=True) print etree.tostring(ret) assert ret.tag == "X" ret = get_object_as_xml(c, C, no_namespace=True) print etree.tostring(ret) assert ret.tag == "C"
def test_subs(self): from lxml import etree from spyne.util.xml import get_xml_as_object from spyne.util.xml import get_object_as_xml m = { "s0": "aa", "s2": "cc", "s3": "dd", } class C(ComplexModel): __namespace__ = "aa" a = Integer b = Integer(sub_name="bb") c = Integer(sub_ns="cc") d = Integer(sub_ns="dd", sub_name="dd") elt = get_object_as_xml(C(a=1, b=2, c=3, d=4), C) print etree.tostring(elt, pretty_print=True) assert elt.xpath("s0:a/text()", namespaces=m) == ["1"] assert elt.xpath("s0:bb/text()", namespaces=m) == ["2"] assert elt.xpath("s2:c/text()", namespaces=m) == ["3"] assert elt.xpath("s3:dd/text()", namespaces=m) == ["4"] c = get_xml_as_object(elt, C) print c assert c.a == 1 assert c.b == 2 assert c.c == 3 assert c.d == 4
def process(value): if value is not None: return etree.tostring(get_object_as_xml( value, self.cls, self.root_tag_name, self.no_namespace), encoding='utf8', pretty_print=self.pretty_print, xml_declaration=False)
def test_any_xml_bytes(self): v = b"<roots><bloody/></roots>" elt = get_object_as_xml(v, AnyXml, 'B', no_namespace=True) eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0]) == v
def test_any_xml_bytes(self): v = b"<roots><bloody/></roots>" elt = get_object_as_xml(v, AnyXml, 'B', no_namespace=True) eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0]) == v
def test_file(self): v = b'aaaa' f = BytesIO(v) elt = get_object_as_xml(File.Value(handle=f), File, 'B') eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode('ascii')
def test_sub_attributes(self): from lxml import etree from spyne.util.xml import get_xml_as_object from spyne.util.xml import get_object_as_xml m = { "s0": "aa", "s2": "cc", "s3": "dd", } class C(ComplexModel): __namespace__ = "aa" a = XmlAttribute(Integer) b = XmlAttribute(Integer(sub_name="bb")) c = XmlAttribute(Integer(sub_ns="cc")) d = XmlAttribute(Integer(sub_ns="dd", sub_name="dd")) elt = get_object_as_xml(C(a=1, b=2, c=3, d=4), C) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath("//*/@a") == ["1"] assert elt.xpath("//*/@bb") == ["2"] assert elt.xpath("//*/@s2:c", namespaces=m) == ["3"] assert elt.xpath("//*/@s3:dd", namespaces=m) == ["4"] c = get_xml_as_object(elt, C) print(c) assert c.a == 1 assert c.b == 2 assert c.c == 3 assert c.d == 4
def test_file(self): v = b"aaaa" f = BytesIO(v) elt = get_object_as_xml(File.Value(handle=f), File, "B") eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode("ascii")
def process(value): return etree.tostring( get_object_as_xml(value, self.cls, self.root_tag_name, self.no_namespace), pretty_print=False, encoding="utf8", xml_declaration=False, )
def test_null_mandatory_attribute(self): class Action (ComplexModel): data = XmlAttribute(M(Unicode)) elt = get_object_as_xml(Action(), Action) eltstr = etree.tostring(elt) print(eltstr) assert eltstr == b'<Action/>'
def test_deserialize(self): class Punk(ComplexModel): __namespace__ = 'some_namespace' a = Unicode b = Integer c = Decimal d = DateTime class Foo(ComplexModel): __namespace__ = 'some_other_namespace' a = Unicode b = Integer c = Decimal d = DateTime e = XmlAttribute(Integer) def __eq__(self, other): # remember that this is a test object assert ( self.a == other.a and self.b == other.b and self.c == other.c and self.d == other.d and self.e == other.e ) return True docs = get_schema_documents([Punk, Foo]) pprint(docs) assert docs['s0'].tag == '{http://www.w3.org/2001/XMLSchema}schema' assert docs['tns'].tag == '{http://www.w3.org/2001/XMLSchema}schema' print() print("the other namespace %r:" % docs['tns'].attrib['targetNamespace']) assert docs['tns'].attrib['targetNamespace'] == 'some_namespace' print(etree.tostring(docs['tns'], pretty_print=True)) print() print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) assert docs['s0'].attrib['targetNamespace'] == 'some_other_namespace' print(etree.tostring(docs['s0'], pretty_print=True)) print() foo = Foo(a=u'a', b=1, c=decimal.Decimal('3.4'), d=datetime(2011,02,20,tzinfo=pytz.utc), e=5) doc = get_object_as_xml(foo, Foo) print(etree.tostring(doc, pretty_print=True)) foo_back = get_xml_as_object(doc, Foo) assert foo_back == foo # as long as it doesn't fail, it's ok. get_validation_schema([Punk, Foo])
def test_deserialize(self): class Punk(ComplexModel): __namespace__ = 'some_namespace' a = Unicode b = Integer c = Decimal d = DateTime class Foo(ComplexModel): __namespace__ = 'some_other_namespace' a = Unicode b = Integer c = Decimal d = DateTime e = XmlAttribute(Integer) def __eq__(self, other): # remember that this is a test object assert ( self.a == other.a and self.b == other.b and self.c == other.c and self.d == other.d and self.e == other.e ) return True docs = get_schema_documents([Punk, Foo]) pprint(docs) assert docs['s0'].tag == '{http://www.w3.org/2001/XMLSchema}schema' assert docs['tns'].tag == '{http://www.w3.org/2001/XMLSchema}schema' print() print("the other namespace %r:" % docs['tns'].attrib['targetNamespace']) assert docs['tns'].attrib['targetNamespace'] == 'some_namespace' print(etree.tostring(docs['tns'], pretty_print=True)) print() print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) assert docs['s0'].attrib['targetNamespace'] == 'some_other_namespace' print(etree.tostring(docs['s0'], pretty_print=True)) print() foo = Foo(a=u'a', b=1, c=decimal.Decimal('3.4'), d=datetime(2011,2,20,tzinfo=pytz.utc), e=5) doc = get_object_as_xml(foo, Foo) print(etree.tostring(doc, pretty_print=True)) foo_back = get_xml_as_object(doc, Foo) assert foo_back == foo # as long as it doesn't fail, it's ok. get_validation_schema([Punk, Foo])
def test_bare_sub_name_ns(self): class Action (ComplexModel): class Attributes(ComplexModel.Attributes): sub_ns = "SOME_NS" sub_name = "Action" data = XmlData(Unicode) must_understand = XmlAttribute(Unicode) elt = get_object_as_xml(Action("x", must_understand="y"), Action) eltstr = etree.tostring(elt) print(eltstr) assert eltstr == b'<ns0:Action xmlns:ns0="SOME_NS" must_understand="y">x</ns0:Action>'
# the default ns prefix is always tns print("the default namespace %r:" % docs['tns'].attrib['targetNamespace']) print(etree.tostring(docs['tns'], pretty_print=True)) print() # Namespace prefixes are assigned like s0, s1, s2, etc... print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) print(etree.tostring(docs['s0'], pretty_print=True)) print() print("the other namespace %r:" % docs['s2'].attrib['targetNamespace']) print(etree.tostring(docs['s2'], pretty_print=True)) print() # Object serialization and deserialization foo = Foo(a='a', b=1, c=3.4, d=datetime(2011, 02, 20), e=5, f='f') doc = get_object_as_xml(foo, Foo) print(etree.tostring(doc, pretty_print=True)) print(get_xml_as_object(doc, Foo)) print() # XmlData example. print("Product output (illustrates XmlData):") product = Product(id=uuid.uuid4(), edition=ProductEdition(id=uuid.uuid4(), name='My edition')) print(etree.tostring(get_object_as_xml(product, Product), pretty_print=True)) # See http://lxml.de/validation.html to see what this could be used for. print(get_validation_schema([Punk, Foo]))
def complex_add(document, cls, tags): complex_type = etree.Element("{%s}complexType" % _ns_xsd) complex_type.set('name', cls.get_type_name()) if cls.Annotations.doc != '' or cls.Annotations.appinfo != None or \ cls.Annotations.__use_parent_doc__: annotation = etree.SubElement(complex_type, "{%s}annotation" % _ns_xsd) if cls.Annotations.doc != '' or cls.Annotations.__use_parent_doc__: doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) if cls.Annotations.__use_parent_doc__: doc.text = getattr(cls, '__doc__') else: doc.text = cls.Annotations.doc _ai = cls.Annotations.appinfo; if _ai != None: appinfo = etree.SubElement(annotation, "{%s}appinfo" % _ns_xsd) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, str) or isinstance(_ai, unicode): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) type_info = cls._type_info if extends is not None: if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception("%r can't extend %r because they are both '{%s}%s'" % (cls, extends, cls.get_namespace(), cls.get_type_name())) if extends.Attributes.exc_interface: # If the parent class is private, it won't be in the schema, so we # need to act as if its attributes are part of cls as well. type_info = cls.get_simple_type_info(cls) else: complex_content = etree.SubElement(complex_type, "{%s}complexContent" % _ns_xsd) extension = etree.SubElement(complex_content, "{%s}extension" % _ns_xsd) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension sequence = etree.Element('{%s}sequence' % _ns_xsd) deferred = deque() choice_tags = defaultdict(lambda: etree.Element('{%s}choice' % _ns_xsd)) for k, v in type_info.items(): a = v.Attributes if a.exc_interface: continue if issubclass(v, XmlAttribute): deferred.append((k,v)) continue document.add(v, tags) name = a.sub_name ns = a.sub_ns if name is None: name = k if ns is not None: name = "{%s}%s" % (ns, name) member = etree.Element(a.schema_tag) if a.schema_tag == '{%s}element' % _ns_xsd: member.set('name', name) member.set('type', v.get_type_name_ns(document.interface)) elif a.schema_tag == '{%s}any' % _ns_xsd and \ (issubclass(v, AnyXml)): if a.namespace is not None: member.set('namespace', a.namespace) if a.process_contents is not None: member.set('processContents', a.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, a.schema_tag)) if a.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(a.min_occurs)) if a.max_occurs != 1: # 1 is the xml schema default val = a.max_occurs if val in (decimal.Decimal('inf'), float('inf')): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if a.default is not None: member.set('default', a.default) if bool(a.nillable) != False: # False is the xml schema default member.set('nillable', 'true') if v.Annotations.doc != '': # Doesn't support multi-language documentation annotation = etree.SubElement(member, "{%s}annotation" % _ns_xsd) doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) doc.text = v.Annotations.doc if a.xml_choice_group is None: sequence.append(member) else: choice_tags[a.xml_choice_group].append(member) sequence.extend(choice_tags.values()) if len(sequence) > 0: sequence_parent.append(sequence) for k,v in deferred: ao = v.attribute_of if ao is None: # others will be added at a later loop attribute = etree.SubElement(complex_type,'{%s}attribute' % _ns_xsd) v.describe(k, attribute, document) continue elts = complex_type.xpath("//xsd:element[@name='%s']" % ao, namespaces={'xsd': _ns_xsd}) if len(elts) == 0: raise ValueError("Element %r not found for XmlAttribute %r." % (ao, k)) elif len(elts) > 1: raise Exception("Xpath returned more than one element %r " "for %r. Not sure what's going on here." % (elts, ao)) else: elt = elts[0] _ct = etree.SubElement(elt, '{%s}complexType' % _ns_xsd) _sc = etree.SubElement(_ct, '{%s}simpleContent' % _ns_xsd) _ext = etree.SubElement(_sc, '{%s}extension' % _ns_xsd) _ext.attrib['base'] = elt.attrib['type'] del elt.attrib['type'] attribute = etree.SubElement(_ext, '{%s}attribute' % _ns_xsd) v.describe(k, attribute, document) document.add_complex_type(cls, complex_type) # simple node element = etree.Element('{%s}element' % _ns_xsd) element.set('name', cls.get_type_name()) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)
i = Integer s = Unicode d = DateTime __repr__ = hier_repr # Instantiate the object instance = SomeObject(i=5, s="str", d=datetime.now()) # Generate schema documents schema_elts = get_schema_documents([SomeObject], 'some_ns') # Serialize the xml schema document for object schema = etree.tostring(schema_elts['tns'], pretty_print=True) # Serialize the object to XML instance_elt = get_object_as_xml(instance, SomeObject) # Serialize the element tree to string data = etree.tostring(instance_elt, pretty_print=True) print(instance) print() print(schema) print(data) # parse the schema document parsed_schema = parse_schema_string(schema)['some_ns'] # Get SomeObject definition from the parsed schema document NewObject = parsed_schema.types['SomeObject']
def test_bytearray(self): v = b'aaaa' elt = get_object_as_xml([v], ByteArray, 'B') eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode('ascii')
def test_any_xml_elt(self): v = E.roots(E.bloody(E.roots())) elt = get_object_as_xml(v, AnyXml, 'B') eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0]) == etree.tostring(v)
def test_bytearray(self): v = b"aaaa" elt = get_object_as_xml([v], ByteArray, "B") eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode("ascii")
def test_fault_detail_as_dict(self): elt = get_object_as_xml(Fault(detail={"this": "that"}), Fault) eltstr = etree.tostring(elt) print(eltstr) assert b'<detail><this>that</this></detail>' in eltstr
# the default ns prefix is always tns print("the default namespace %r:" % docs['tns'].attrib['targetNamespace']) print(etree.tostring(docs['tns'], pretty_print=True)) print() # Namespace prefixes are assigned like s0, s1, s2, etc... print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) print(etree.tostring(docs['s0'], pretty_print=True)) print() print("the other namespace %r:" % docs['s2'].attrib['targetNamespace']) print(etree.tostring(docs['s2'], pretty_print=True)) print() # Object serialization and deserialization foo = Foo(a='a', b=1, c=3.4, d=datetime(2011, 02, 20), e=5, f='f') doc = get_object_as_xml(foo, Foo) print(etree.tostring(doc, pretty_print=True)) print(get_xml_as_object(doc, Foo)) print() # XmlData example. print("Product output (illustrates XmlData):") product = Product(id=uuid.uuid4(), edition=ProductEdition(id=uuid.uuid4(), name='My edition')) print(etree.tostring(get_object_as_xml(product, Product), pretty_print=True)) # See http://lxml.de/validation.html to see what this could be used for. print(get_validation_schema([Punk, Foo]))
def complex_add(document, cls, tags): complex_type = etree.Element(XSD('complexType')) complex_type.set('name', cls.get_type_name()) doc_text = cls.get_documentation() if doc_text or cls.Annotations.appinfo is not None: annotation = etree.SubElement(complex_type, XSD('annotation')) if doc_text: doc = etree.SubElement(annotation, XSD('documentation')) doc.text = doc_text _ai = cls.Annotations.appinfo if _ai is not None: appinfo = etree.SubElement(annotation, XSD('appinfo')) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, str) or isinstance(_ai, unicode): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) type_info = cls._type_info if extends is not None: if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception("%r can't extend %r because they are both '{%s}%s'" % (cls, extends, cls.get_namespace(), cls.get_type_name())) if extends.Attributes.exc_interface: # If the parent class is private, it won't be in the schema, so we # need to act as if its attributes are part of cls as well. type_info = cls.get_simple_type_info(cls) else: complex_content = etree.SubElement(complex_type, XSD('complexContent')) extension = etree.SubElement(complex_content, XSD('extension')) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension xtba_key, xtba_type = cls.Attributes._xml_tag_body_as if xtba_key is not None: _sc = etree.SubElement(sequence_parent, XSD('simpleContent')) xtba_ext = etree.SubElement(_sc, XSD('extension')) xtba_ext.attrib['base'] = xtba_type.type.get_type_name_ns( document.interface) sequence = etree.Element(XSD('sequence')) deferred = deque() choice_tags = defaultdict(lambda: etree.Element(XSD('choice'))) for k, v in type_info.items(): assert isinstance(k, string_types) assert issubclass(v, ModelBase) a = v.Attributes if a.exc_interface: continue if issubclass(v, XmlData): continue if issubclass(v, XmlAttribute): deferred.append((k,v)) continue document.add(v, tags) name = a.sub_name if name is None: name = k #ns = a.sub_ns #if ns is not None: # name = "{%s}%s" % (ns, name) type_name_ns = v.get_type_name_ns(document.interface) if v.__extends__ is not None and v.__orig__ is not None and \ _check_extension_attrs(v) is None: type_name_ns = v.__orig__.get_type_name_ns(document.interface) member = etree.Element(a.schema_tag) if a.schema_tag == XSD('element'): member.set('name', name) member.set('type', type_name_ns) elif a.schema_tag == XSD('any') and issubclass(v, AnyXml): if a.namespace is not None: member.set('namespace', a.namespace) if a.process_contents is not None: member.set('processContents', a.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, a.schema_tag)) if a.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(a.min_occurs)) if a.max_occurs != 1: # 1 is the xml schema default val = a.max_occurs if val in (D('inf'), float('inf')): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if a.default is not None: member.set('default', _prot.to_string(v, a.default)) if bool(a.nillable) != False: # False is the xml schema default member.set('nillable', 'true') v_doc_text = v.get_documentation() if v_doc_text: # Doesn't support multi-language documentation annotation = etree.SubElement(member, XSD('annotation')) doc = etree.SubElement(annotation, XSD('documentation')) doc.text = doc_text if a.xml_choice_group is None: sequence.append(member) else: choice_tags[a.xml_choice_group].append(member) sequence.extend(choice_tags.values()) if len(sequence) > 0: sequence_parent.append(sequence) _ext_elements = dict() for k,v in deferred: ao = v.attribute_of if ao is None: attribute = etree.Element(XSD('attribute')) xml_attribute_add(v, k, attribute, document) if xtba_key is None: complex_type.append(attribute) else: xtba_ext.append(attribute) continue elts = complex_type.xpath("//xsd:element[@name='%s']" % ao, namespaces={'xsd': _ns_xsd}) if len(elts) == 0: raise ValueError("Element %r not found for XmlAttribute %r." % (ao, k)) elif len(elts) > 1: raise Exception("Xpath returned more than one element %r " "for %r. Not sure what's going on here." % (elts, ao)) else: elt = elts[0] _ext = _ext_elements.get(ao, None) if _ext is None: _ct = etree.SubElement(elt, XSD('complexType')) _sc = etree.SubElement(_ct, XSD('simpleContent')) _ext = etree.SubElement(_sc, XSD('extension')) _ext_elements[ao] = _ext _ext.attrib['base'] = elt.attrib['type'] del elt.attrib['type'] attribute = etree.SubElement(_ext, XSD('attribute')) xml_attribute_add(v, k, attribute, document) document.add_complex_type(cls, complex_type) # simple node complex_type_name = cls.Attributes.sub_name or cls.get_type_name() element = etree.Element(XSD('element')) element.set('name', complex_type_name) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)
def process(value): if value is not None: return etree.tostring(get_object_as_xml(value, self.cls, self.root_tag_name, self.no_namespace), encoding='utf8', pretty_print=self.pretty_print, xml_declaration=False)
def complex_add(document, cls): complex_type = etree.Element("{%s}complexType" % _ns_xsd) complex_type.set('name', cls.get_type_name()) if cls.Annotations.doc != '' or cls.Annotations.appinfo != None: annotation = etree.SubElement(complex_type, "{%s}annotation" % _ns_xsd) if cls.Annotations.doc != '': doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) doc.text = cls.Annotations.doc _ai = cls.Annotations.appinfo; if _ai != None: appinfo = etree.SubElement(annotation, "{%s}appinfo" % _ns_xsd) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, str) or isinstance(_ai, unicode): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) if not (extends is None): if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception("%r can't extend %r because they are all '{%s}%s'" % (cls, extends, cls.get_type_name(), cls.get_namespace())) else: complex_content = etree.SubElement(complex_type, "{%s}complexContent" % _ns_xsd) extension = etree.SubElement(complex_content, "{%s}extension" % _ns_xsd) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension sequence = etree.SubElement(sequence_parent, '{%s}sequence' % _ns_xsd) for k, v in cls._type_info.items(): if issubclass(v, XmlAttribute): attribute = etree.SubElement(complex_type, '{%s}attribute' % _ns_xsd) v.describe(k, attribute, document) continue if not issubclass(v, cls): document.add(v) member = etree.SubElement(sequence, v.Attributes.schema_tag) if v.Attributes.schema_tag == '{%s}element' % _ns_xsd: member.set('name', k) member.set('type', v.get_type_name_ns(document.interface)) elif v.Attributes.schema_tag == '{%s}any' % _ns_xsd and \ (issubclass(v, AnyXml)): if v.Attributes.namespace is not None: member.set('namespace', v.Attributes.namespace) if v.Attributes.process_contents is not None: member.set('processContents', v.Attributes.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, v.Attributes.schema_tag)) if v.Attributes.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(v.Attributes.min_occurs)) if v.Attributes.max_occurs != 1: # 1 is the xml schema default val = v.Attributes.max_occurs if val == float('inf'): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if bool(v.Attributes.nillable) != False: # False is the xml schema default member.set('nillable', 'true') document.add_complex_type(cls, complex_type) # simple node element = etree.Element('{%s}element' % _ns_xsd) element.set('name', cls.get_type_name()) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)
def test_any_xml_elt(self): v = E.roots(E.bloody(E.roots())) elt = get_object_as_xml(v, AnyXml, 'B') eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0]) == etree.tostring(v)
def test_any_xml_text(self): v = u"<roots><bloody/></roots>" elt = get_object_as_xml(v, AnyXml, 'B', no_namespace=True) eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0], encoding="unicode") == v
def complex_add(document, cls): complex_type = etree.Element("{%s}complexType" % _ns_xsd) complex_type.set('name', cls.get_type_name()) if cls.Annotations.doc != '' or cls.Annotations.appinfo != None or \ cls.Annotations.__use_parent_doc__: annotation = etree.SubElement(complex_type, "{%s}annotation" % _ns_xsd) if cls.Annotations.doc != '' or cls.Annotations.__use_parent_doc__: doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) if cls.Annotations.__use_parent_doc__: doc.text = getattr(cls, '__doc__') else: doc.text = cls.Annotations.doc _ai = cls.Annotations.appinfo if _ai != None: appinfo = etree.SubElement(annotation, "{%s}appinfo" % _ns_xsd) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, str) or isinstance(_ai, unicode): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) type_info = cls._type_info if extends is not None: if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception( "%r can't extend %r because they are both '{%s}%s'" % (cls, extends, cls.get_type_name(), cls.get_namespace())) if extends.Attributes.exc_interface: # If the parent class is private, it won't be in the schema, so we # need to act as if its attributes are part of cls as well. type_info = cls.get_simple_type_info(cls) else: complex_content = etree.SubElement(complex_type, "{%s}complexContent" % _ns_xsd) extension = etree.SubElement(complex_content, "{%s}extension" % _ns_xsd) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension sequence = etree.SubElement(sequence_parent, '{%s}sequence' % _ns_xsd) for k, v in type_info.items(): if issubclass(v, XmlAttribute): attribute = etree.SubElement(complex_type, '{%s}attribute' % _ns_xsd) v.describe(k, attribute, document) continue if v.Attributes.exc_interface: continue if not issubclass(v, cls): document.add(v) member = etree.SubElement(sequence, v.Attributes.schema_tag) if v.Attributes.schema_tag == '{%s}element' % _ns_xsd: member.set('name', k) member.set('type', v.get_type_name_ns(document.interface)) elif v.Attributes.schema_tag == '{%s}any' % _ns_xsd and \ (issubclass(v, AnyXml)): if v.Attributes.namespace is not None: member.set('namespace', v.Attributes.namespace) if v.Attributes.process_contents is not None: member.set('processContents', v.Attributes.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, v.Attributes.schema_tag)) if v.Attributes.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(v.Attributes.min_occurs)) if v.Attributes.max_occurs != 1: # 1 is the xml schema default val = v.Attributes.max_occurs if val == decimal.Decimal('inf'): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if bool(v.Attributes.nillable ) != False: # False is the xml schema default member.set('nillable', 'true') document.add_complex_type(cls, complex_type) # simple node element = etree.Element('{%s}element' % _ns_xsd) element.set('name', cls.get_type_name()) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)
def test_any_xml_text(self): v = u"<roots><bloody/></roots>" elt = get_object_as_xml(v, AnyXml, 'B', no_namespace=True) eltstr = etree.tostring(elt) print(eltstr) assert etree.tostring(elt[0], encoding="unicode") == v
s = Unicode d = DateTime __repr__ = own_repr # Instantiate the object instance = SomeObject(i=5, s="str", d=datetime.now()) # Generate schema documents schema_elts = get_schema_documents([SomeObject], 'some_ns') # Serialize the xml schema document for object schema = etree.tostring(schema_elts['tns'], pretty_print=True) # Serialize the object to XML instance_elt = get_object_as_xml(instance, SomeObject) # Serialize the element tree to string data = etree.tostring(instance_elt, pretty_print=True) print instance print print schema print data # parse the schema document parsed_schema = parse_schema_string(schema)['some_ns'] # Get SomeObject definition from the parsed schema document NewObject = parsed_schema.types['SomeObject']
__namespace__ = 'some_other_namespace' a = String b = Integer c = Decimal d = DateTime e = XmlAttribute(Integer) docs = get_schema_documents([Punk, Foo]) pprint(docs) print() # the default ns prefix is always tns print("the default namespace %r:" % docs['tns'].attrib['targetNamespace']) print(etree.tostring(docs['tns'], pretty_print=True)) print() # Namespace prefixes are assigned like s0, s1, s2, etc... print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) print(etree.tostring(docs['s0'], pretty_print=True)) foo = Foo(a='a', b=1, c=3.4, d=datetime(2011,02,20),e=5) doc = get_object_as_xml(foo) print(etree.tostring(doc, pretty_print=True)) print(get_xml_as_object(Foo, doc)) # See http://lxml.de/validation.html to see what this could be used for. print(get_validation_schema([Punk, Foo]))
def complex_add(document, cls, tags): complex_type = etree.Element("{%s}complexType" % _ns_xsd) complex_type.set('name', cls.get_type_name()) if cls.Annotations.doc != '' or cls.Annotations.appinfo != None or \ cls.Annotations.__use_parent_doc__: annotation = etree.SubElement(complex_type, "{%s}annotation" % _ns_xsd) if cls.Annotations.doc != '' or cls.Annotations.__use_parent_doc__: doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) if cls.Annotations.__use_parent_doc__: doc.text = getattr(cls, '__doc__') else: doc.text = cls.Annotations.doc _ai = cls.Annotations.appinfo if _ai != None: appinfo = etree.SubElement(annotation, "{%s}appinfo" % _ns_xsd) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, str) or isinstance(_ai, unicode): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) type_info = cls._type_info if extends is not None: if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception( "%r can't extend %r because they are both '{%s}%s'" % (cls, extends, cls.get_namespace(), cls.get_type_name())) if extends.Attributes.exc_interface: # If the parent class is private, it won't be in the schema, so we # need to act as if its attributes are part of cls as well. type_info = cls.get_simple_type_info(cls) else: complex_content = etree.SubElement(complex_type, "{%s}complexContent" % _ns_xsd) extension = etree.SubElement(complex_content, "{%s}extension" % _ns_xsd) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension sequence = etree.Element('{%s}sequence' % _ns_xsd) deferred = deque() choice_tags = defaultdict(lambda: etree.Element('{%s}choice' % _ns_xsd)) for k, v in type_info.items(): a = v.Attributes if a.exc_interface: continue if issubclass(v, XmlAttribute): deferred.append((k, v)) continue document.add(v, tags) name = a.sub_name ns = a.sub_ns if name is None: name = k if ns is not None: name = "{%s}%s" % (ns, name) member = etree.Element(a.schema_tag) if a.schema_tag == '{%s}element' % _ns_xsd: member.set('name', name) member.set('type', v.get_type_name_ns(document.interface)) elif a.schema_tag == '{%s}any' % _ns_xsd and \ (issubclass(v, AnyXml)): if a.namespace is not None: member.set('namespace', a.namespace) if a.process_contents is not None: member.set('processContents', a.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, a.schema_tag)) if a.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(a.min_occurs)) if a.max_occurs != 1: # 1 is the xml schema default val = a.max_occurs if val in (decimal.Decimal('inf'), float('inf')): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if a.default is not None: member.set('default', _prot.to_string(v, a.default)) if bool(a.nillable) != False: # False is the xml schema default member.set('nillable', 'true') if v.Annotations.doc != '': # Doesn't support multi-language documentation annotation = etree.SubElement(member, "{%s}annotation" % _ns_xsd) doc = etree.SubElement(annotation, "{%s}documentation" % _ns_xsd) doc.text = v.Annotations.doc if a.xml_choice_group is None: sequence.append(member) else: choice_tags[a.xml_choice_group].append(member) sequence.extend(choice_tags.values()) if len(sequence) > 0: sequence_parent.append(sequence) for k, v in deferred: ao = v.attribute_of if ao is None: # others will be added at a later loop attribute = etree.SubElement(complex_type, '{%s}attribute' % _ns_xsd) xml_attribute_add(v, k, attribute, document) continue elts = complex_type.xpath("//xsd:element[@name='%s']" % ao, namespaces={'xsd': _ns_xsd}) if len(elts) == 0: raise ValueError("Element %r not found for XmlAttribute %r." % (ao, k)) elif len(elts) > 1: raise Exception("Xpath returned more than one element %r " "for %r. Not sure what's going on here." % (elts, ao)) else: elt = elts[0] _ct = etree.SubElement(elt, '{%s}complexType' % _ns_xsd) _sc = etree.SubElement(_ct, '{%s}simpleContent' % _ns_xsd) _ext = etree.SubElement(_sc, '{%s}extension' % _ns_xsd) _ext.attrib['base'] = elt.attrib['type'] del elt.attrib['type'] attribute = etree.SubElement(_ext, '{%s}attribute' % _ns_xsd) xml_attribute_add(v, k, attribute, document) document.add_complex_type(cls, complex_type) # simple node complex_type_name = cls.Attributes.sub_name or cls.get_type_name() element = etree.Element('{%s}element' % _ns_xsd) element.set('name', complex_type_name) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)
def test_bytearray(self): v = b'aaaa' elt = get_object_as_xml([v], ByteArray, 'B') eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode('ascii')
class Foo(ComplexModel): __namespace__ = 'some_other_namespace' a = String b = Integer c = Decimal d = DateTime e = XmlAttribute(Integer) docs = get_schema_documents([Punk, Foo]) pprint(docs) print() # the default ns prefix is always tns print("the default namespace %r:" % docs['tns'].attrib['targetNamespace']) print(etree.tostring(docs['tns'], pretty_print=True)) print() # Namespace prefixes are assigned like s0, s1, s2, etc... print("the other namespace %r:" % docs['s0'].attrib['targetNamespace']) print(etree.tostring(docs['s0'], pretty_print=True)) foo = Foo(a='a', b=1, c=3.4, d=datetime(2011, 02, 20), e=5) doc = get_object_as_xml(foo) print(etree.tostring(doc, pretty_print=True)) print(get_xml_as_object(Foo, doc)) # See http://lxml.de/validation.html to see what this could be used for. print(get_validation_schema([Punk, Foo]))
def complex_add(document, cls, tags): complex_type = etree.Element(XSD('complexType')) complex_type.set('name', cls.get_type_name()) doc_text = cls.get_documentation() if doc_text or cls.Annotations.appinfo is not None: annotation = etree.SubElement(complex_type, XSD('annotation')) if doc_text: doc = etree.SubElement(annotation, XSD('documentation')) doc.text = doc_text _ai = cls.Annotations.appinfo if _ai is not None: appinfo = etree.SubElement(annotation, XSD('appinfo')) if isinstance(_ai, dict): dict_to_etree(_ai, appinfo) elif isinstance(_ai, string_types): appinfo.text = _ai elif isinstance(_ai, etree._Element): appinfo.append(_ai) else: from spyne.util.xml import get_object_as_xml appinfo.append(get_object_as_xml(_ai)) sequence_parent = complex_type extends = getattr(cls, '__extends__', None) type_info = cls._type_info if extends is not None: if (extends.get_type_name() == cls.get_type_name() and extends.get_namespace() == cls.get_namespace()): raise Exception( "%r can't extend %r because they are both '{%s}%s'" % (cls, extends, cls.get_namespace(), cls.get_type_name())) if extends.Attributes.exc_interface: # If the parent class is private, it won't be in the schema, so we # need to act as if its attributes are part of cls as well. type_info = cls.get_simple_type_info(cls) else: complex_content = etree.SubElement(complex_type, XSD('complexContent')) extension = etree.SubElement(complex_content, XSD('extension')) extension.set('base', extends.get_type_name_ns(document.interface)) sequence_parent = extension if cls.Attributes._xml_tag_body_as is not None: for xtba_key, xtba_type in cls.Attributes._xml_tag_body_as: _sc = etree.SubElement(sequence_parent, XSD('simpleContent')) xtba_ext = etree.SubElement(_sc, XSD('extension')) xtba_ext.attrib['base'] = xtba_type.type.get_type_name_ns( document.interface) sequence = etree.Element(XSD('sequence')) deferred = deque() choice_tags = defaultdict(lambda: etree.Element(XSD('choice'))) for k, v in type_info.items(): assert isinstance(k, string_types) assert issubclass(v, ModelBase) a = v.Attributes if a.exc_interface: continue if issubclass(v, XmlData): continue if issubclass(v, XmlAttribute): deferred.append((k, v)) continue document.add(v, tags) name = a.sub_name if name is None: name = k #ns = a.sub_ns #if ns is not None: # name = "{%s}%s" % (ns, name) type_name_ns = v.get_type_name_ns(document.interface) if v.__extends__ is not None and v.__orig__ is not None and \ _check_extension_attrs(v) is None: type_name_ns = v.__orig__.get_type_name_ns(document.interface) member = etree.Element(a.schema_tag) if a.schema_tag == XSD('element'): member.set('name', name) member.set('type', type_name_ns) elif a.schema_tag == XSD('any') and issubclass(v, AnyXml): if a.namespace is not None: member.set('namespace', a.namespace) if a.process_contents is not None: member.set('processContents', a.process_contents) else: raise ValueError("Unhandled schema_tag / type combination. %r %r" % (v, a.schema_tag)) if a.min_occurs != 1: # 1 is the xml schema default member.set('minOccurs', str(a.min_occurs)) if a.max_occurs != 1: # 1 is the xml schema default val = a.max_occurs if val in (D('inf'), float('inf')): val = 'unbounded' else: val = str(val) member.set('maxOccurs', val) if a.default is not None: member.set('default', _prot.to_unicode(v, a.default)) if bool(a.nillable) != False: # False is the xml schema default member.set('nillable', 'true') v_doc_text = v.get_documentation() if v_doc_text: # Doesn't support multi-language documentation annotation = etree.SubElement(member, XSD('annotation')) doc = etree.SubElement(annotation, XSD('documentation')) doc.text = v_doc_text if a.xml_choice_group is None: sequence.append(member) else: choice_tags[a.xml_choice_group].append(member) sequence.extend(choice_tags.values()) if len(sequence) > 0: sequence_parent.append(sequence) _ext_elements = dict() for k, v in deferred: attribute = etree.Element(XSD('attribute')) xml_attribute_add(v, k, attribute, document) if cls.Attributes._xml_tag_body_as is None: sequence_parent.append(attribute) else: xtba_ext.append(attribute) document.add_complex_type(cls, complex_type) # simple node complex_type_name = cls.Attributes.sub_name or cls.get_type_name() element = etree.Element(XSD('element')) element.set('name', complex_type_name) element.set('type', cls.get_type_name_ns(document.interface)) document.add_element(cls, element)