将描述的模式zope 3对象转换为xml并返回
z3c.schema2xml的Python项目详细描述
架构到XML
简介
这个包可以将zope 3模式描述的对象转换为简单的 XML结构。它还可以将这个xml转换回对象。 导出和导入过程完全由模式驱动;任何 此系统在上看不到架构中未描述的属性 全部。
此系统可用于为Zope 3创建导出和导入系统 应用。它还可以用来提供 用于其他目的的对象,例如xslt转换,甚至只是 以获取用于索引目的的全文表示。
包位于lxml上,用于序列化为XML。
序列化
我们首先定义一个简单的zope 3模式:
>>> from zope import interface, schema >>> class IName(interface.Interface): ... first_name = schema.TextLine(title=u'First name') ... last_name = schema.TextLine(title=u'Last name')
现在让我们创建一个实现此架构的类:
>>> from zope.interface import implements >>> class Name(object): ... implements(IName) ... def __init__(self, first_name, last_name): ... self.first_name = first_name ... self.last_name = last_name
让我们制作一个类的实例:
>>> name = Name('Karel', 'Titulaer')
现在我们将其序列化为xml:
>>> from z3c.schema2xml import serialize >>> print serialize('container', IName, name) <container> <first_name>Karel</first_name> <last_name>Titulaer</last_name> </container>
这也适用于其他类型的字段:
>>> from zope import interface, schema >>> class IAddress(interface.Interface): ... street_name = schema.TextLine(title=u'Street name') ... number = schema.Int(title=u'House number') >>> class Address(object): ... implements(IAddress) ... def __init__(self, street_name, number): ... self.street_name = street_name ... self.number = number >>> address = Address('Hofplein', 42) >>> print serialize('container', IAddress, address) <container> <street_name>Hofplein</street_name> <number>42</number> </container>
如果未填写字段,则序列化将导致空 元素:
>>> address2 = Address(None, None) >>> print serialize('container', IAddress, address2) <container> <street_name/> <number/> </container>
如果架构用自己的架构定义了一个对象字段,则序列化 也可以处理此问题:
>>> class IPerson(interface.Interface): ... name = schema.Object(title=u"Name", schema=IName) ... address = schema.Object(title=u"Address", schema=IAddress) >>> class Person(object): ... implements(IPerson) ... def __init__(self, name, address): ... self.name = name ... self.address = address >>> person = Person(name, address) >>> print serialize('person', IPerson, person) <person> <name> <first_name>Karel</first_name> <last_name>Titulaer</last_name> </name> <address> <street_name>Hofplein</street_name> <number>42</number> </address> </person>
模式还可以定义一个列表字段,其中包含自己的元素 架构。让我们创建一个对象并序列化它:
>>> class ICommission(interface.Interface): ... members = schema.List( ... title=u"Commission", ... value_type=schema.Object(__name__='person', ... schema=IPerson))
注意,我们必须为 用于此处的值类型,否则我们没有要序列化到的名称 XML与。
>>> class Commission(object): ... implements(ICommission) ... def __init__(self, members): ... self.members = members>>> commission = Commission( ... [person, Person(Name('Chriet', 'Titulaer'), Address('Ruimteweg', 3))]) >>> print serialize('commission', ICommission, commission) <commission> <members> <person> <name> <first_name>Karel</first_name> <last_name>Titulaer</last_name> </name> <address> <street_name>Hofplein</street_name> <number>42</number> </address> </person> <person> <name> <first_name>Chriet</first_name> <last_name>Titulaer</last_name> </name> <address> <street_name>Ruimteweg</street_name> <number>3</number> </address> </person> </members> </commission>
每当我们尝试序列化 没有序列化程序:
>>> class IWithNonSerializableField(interface.Interface): ... field = schema.Field(title=u"Commission") >>> class NotSerializable(object): ... implements(IWithNonSerializableField) ... def __init__(self, value): ... self.field = value >>> not_serializable = NotSerializable(None) >>> serialize('noway', IWithNonSerializableField, not_serializable) Traceback (most recent call last): ... TypeError: ('Could not adapt', <zope.schema._bootstrapfields.Field object at ...>, <InterfaceClass z3c.schema2xml._schema2xml.IXMLGenerator>)
反序列化
现在我们要根据一个模式将xml反序列化为 提供此架构。
>>> from z3c.schema2xml import deserialize >>> xml = ''' ... <container> ... <first_name>Karel</first_name> ... <last_name>Titulaer</last_name> ... </container> ... ''' >>> name = Name('', '') >>> deserialize(xml, IName, name) >>> name.first_name u'Karel' >>> name.last_name u'Titulaer'
XML中字段的顺序无关紧要:
>>> xml = ''' ... <container> ... <last_name>Titulaer</last_name> ... <first_name>Karel</first_name> ... </container> ... ''' >>> name = Name('', '') >>> deserialize(xml, IName, name) >>> name.first_name u'Karel' >>> name.last_name u'Titulaer'
反序列化后,对象还提供架构接口:
>>> IName.providedBy(name) True
这也适用于其他类型的字段:
>>> xml = ''' ... <container> ... <street_name>Hofplein</street_name> ... <number>42</number> ... </container> ... ''' >>> address = Address('', 0) >>> deserialize(xml, IAddress, address) >>> address.street_name u'Hofplein' >>> address.number 42
如果架构用自己的架构定义了一个对象字段,则序列化 也可以处理此问题:
>>> xml = ''' ... <person> ... <name> ... <first_name>Karel</first_name> ... <last_name>Titulaer</last_name> ... </name> ... <address> ... <street_name>Hofplein</street_name> ... <number>42</number> ... </address> ... </person> ... ''' >>> person = Person(Name('', ''), Address('', 0)) >>> deserialize(xml, IPerson, person) >>> person.name.first_name u'Karel' >>> person.name.last_name u'Titulaer' >>> person.address.street_name u'Hofplein' >>> person.address.number 42 >>> IPerson.providedBy(person) True >>> IName.providedBy(person.name) True >>> IAddress.providedBy(person.address) True
同样,字段以xml形式出现的顺序也不重要:
>>> xml = ''' ... <person> ... <address> ... <number>42</number> ... <street_name>Hofplein</street_name> ... </address> ... <name> ... <last_name>Titulaer</last_name> ... <first_name>Karel</first_name> ... </name> ... </person> ... ''' >>> person = Person(Name('', ''), Address('', 0)) >>> deserialize(xml, IPerson, person) >>> person.name.first_name u'Karel' >>> person.name.last_name u'Titulaer' >>> person.address.street_name u'Hofplein' >>> person.address.number 42 >>> IPerson.providedBy(person) True >>> IName.providedBy(person.name) True >>> IAddress.providedBy(person.address) True >>> xml = ''' ... <commission> ... <members> ... <person> ... <name> ... <first_name>Karel</first_name> ... <last_name>Titulaer</last_name> ... </name> ... <address> ... <street_name>Hofplein</street_name> ... <number>42</number> ... </address> ... </person> ... <person> ... <name> ... <first_name>Chriet</first_name> ... <last_name>Titulaer</last_name> ... </name> ... <address> ... <street_name>Ruimteweg</street_name> ... <number>3</number> ... </address> ... </person> ... </members> ... </commission> ... ''' >>> commission = Commission([]) >>> deserialize(xml, ICommission, commission) >>> len(commission.members) 2 >>> member = commission.members[0] >>> member.name.first_name u'Karel' >>> member.address.street_name u'Hofplein' >>> member = commission.members[1] >>> member.name.first_name u'Chriet' >>> member.address.street_name u'Ruimteweg'
当xml元素为空时,结果值应为none:
>>> from z3c.schema2xml import deserialize >>> xml = ''' ... <container> ... <first_name></first_name> ... <last_name/> ... </container> ... ''' >>> name = Name('', '') >>> deserialize(xml, IName, name) >>> name.first_name is None True >>> name.last_name is None True
对于所有类型的字段,如字符串和整数…:
>>> xml = ''' ... <container> ... <street_name/> ... <number/> ... </container> ... ''' >>> address = Address('', 0) >>> deserialize(xml, IAddress, address) >>> address.street_name is None True >>> address.number is None True
…以及子对象的字段(但不是子对象本身!):
>>> xml = ''' ... <person> ... <name> ... <first_name/> ... <last_name/> ... </name> ... <address> ... <street_name/> ... <number/> ... </address> ... </person> ... ''' >>> person = Person(Name('', ''), Address('', 0)) >>> deserialize(xml, IPerson, person) >>> person.name.first_name is None True >>> person.name.last_name is None True >>> IPerson.providedBy(person) True >>> IName.providedBy(person.name) True >>> person.address is None False >>> person.address.street_name is None True >>> person.address.number is None True >>> IAddress.providedBy(person.address) True
类似地,如果需要序列,则该值应为空序列:
>>> xml = ''' ... <commission> ... <members/> ... </commission> ... ''' >>> commission = Commission([]) >>> deserialize(xml, ICommission, commission) >>> len(commission.members) 0
textline、int、object和list都刚刚测试过。现在跟着测试 对于其他具有序列化程序的字段类型。
日期时间
日期时间对象:
>>> from datetime import datetime >>> class IWithDatetime(interface.Interface): ... datetime = schema.Datetime(title=u'Date and time') >>> class WithDatetime(object): ... implements(IWithDatetime) ... def __init__(self, datetime): ... self.datetime = datetime >>> with_datetime = WithDatetime(datetime(2006, 12, 31)) >>> xml = serialize('container', IWithDatetime, with_datetime) >>> print xml <container> <datetime>2006-12-31T00:00:00</datetime> </container> >>> new_datetime = WithDatetime(None) >>> deserialize(xml, IWithDatetime, new_datetime) >>> new_datetime.datetime.year 2006 >>> new_datetime.datetime.month 12 >>> new_datetime.datetime.day 31
让我们在未填写字段的情况下进行尝试:
>>> with_datetime = WithDatetime(None) >>> xml = serialize('container', IWithDatetime, with_datetime) >>> print xml <container> <datetime/> </container> >>> new_datetime= WithDatetime(None) >>> deserialize(xml, IWithDatetime, new_datetime) >>> new_datetime.datetime is None True
选择
选择字段。目前,我们只处理具有 文本值:
>>> from zc.sourcefactory.basic import BasicSourceFactory >>> class ChoiceSource(BasicSourceFactory): ... def getValues(self): ... return [u'alpha', u'beta'] >>> class IWithChoice(interface.Interface): ... choice = schema.Choice(title=u'Choice', required=False, ... source=ChoiceSource()) >>> class WithChoice(object): ... implements(IWithChoice) ... def __init__(self, choice): ... self.choice = choice >>> with_choice = WithChoice('alpha') >>> xml = serialize('container', IWithChoice, with_choice) >>> print xml <container> <choice>alpha</choice> </container> >>> new_choice = WithChoice(None) >>> deserialize(xml, IWithChoice, new_choice) >>> new_choice.choice 'alpha' >>> with_choice = WithChoice(None) >>> xml = serialize('container', IWithChoice, with_choice) >>> print xml <container> <choice/> </container> >>> deserialize(xml, IWithChoice, new_choice) >>> new_choice.choice is None True
设置
集合字段与列表字段非常相似:
>>> class IWithSet(interface.Interface): ... set = schema.Set(title=u'Set', required=False, ... value_type=schema.Choice(__name__='choice', ... source=ChoiceSource())) >>> class WithSet(object): ... implements(IWithSet) ... def __init__(self, set): ... self.set = set >>> with_set = WithSet(set(['alpha'])) >>> xml = serialize('container', IWithSet, with_set) >>> print xml <container> <set> <choice>alpha</choice> </set> </container> >>> with_set = WithSet(set(['alpha', 'beta'])) >>> xml = serialize('container', IWithSet, with_set) >>> print xml <container> <set> <choice>alpha</choice> <choice>beta</choice> </set> </container> >>> new_set = WithSet(None) >>> deserialize(xml, IWithSet, new_set) >>> new_set.set set(['alpha', 'beta'])
更改
1.0(2008-12-05)
- 更改了对grokcore.component的依赖关系,因此 在直zope 3应用程序中也很有用。
- 对lxml 2.0.9运行测试。
0.10(2008-03-10)
- 首先登录svn.zope.org。