PyXB:创建更多匿名类型的刚性实例

时间:2014-06-23 08:08:24

标签: python xsd pyxb

是否可以使用PyXB从具有匿名复杂类型的XSD生成模块,该模块可以进行一些基本的类型和约束检查?



这是我到目前为止所做的事情:

使用第三方(匿名)XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.foo.com" xmlns="http://www.foo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="ResultSet">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" minOccurs="0" name="Bar">
          <xs:complexType>
            <xs:sequence>
              <xs:element minOccurs="1" name="code" type="xs:string"/>
              <xs:element minOccurs="0" name="description" type="xs:string"/>
              <xs:element minOccurs="0" name="name" type="xs:string"/>
            </xs:sequence>
            <xs:attribute name="href" type="xs:string"/>
            <xs:attribute name="id" type="xs:string"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

我生成了一个python模块:

> pyxbgen -u Foo.xsd -m Foo
Python for http://www.foo.com requires 1 modules
> ls
Foo.py  Foo.xsd

然后在python解释器中,我能够创建一个ResultSet实例并在Bar下创建条目:

> python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyxb
>>> import Foo
>>> Foo
<module 'Foo' from 'Foo.py'>
>>> rs = Foo.ResultSet()
>>> rs
<Foo.CTD_ANON object at 0x7f7360834950>
>>> rs.Bar
<pyxb.binding.content._PluralBinding object at 0x7f7360834a90>

>>> rs.Bar.append( pyxb.BIND( name='a', code='b', description ='c' ) )
>>> rs.Bar
<pyxb.binding.content._PluralBinding object at 0x7f39f1018a90>
>>> [x for x in rs.Bar ]
[<Foo.CTD_ANON_ object at 0x7f39f1018b90>]

我可以与rs.Bar[0]的成员进行互动。

但困扰我的是我也可以:

>>> rs.Bar.append( pyxb.BIND( name='a'  ) )
即使匿名code中的complexType元素属性为minOccurs="1"

也会接受它。我通过阅读StackOverflow上的文档和其他一些问题来收集PyXB试图对动态数据类型进行逆向工程,这可能解释了它的宽容性。

我希望尽可能在整个过程中覆盖一些东西,这让我基本上可以说:

>>> rs.Bar.append( Something( name='a', code='b' ) )

让它抱怨任何缺少的参数。到目前为止,我已经仔细考虑编写自己的函数,使用适当的参数返回pyxb.BIND()的结果,但这意味着相当程度的人工干预。

PyXB有没有办法自动创建这样的智能?

1 个答案:

答案 0 :(得分:1)

由于逆向工程,PyXB不是允许的,但是因为它在构造元素时没有验证元素,在分配元素时也不验证复杂类型。这是因为它可能需要多个Python语句来为元素分配必要的内容:它始终可以通过pyxb.BIND()的参数合理地提供。

例如,您可以通过执行以下操作来完成代码:

rs.Bar.append( pyxb.BIND( name='a'  ) )
rs.Bar[-1].code = '42'

此时rs有效。

如果要在附加对象的位置执行验证,则应使用中间函数来验证附加的元素。以下显示了在传入参数可能是未解析的pyxb.BIND结构的情况下如何执行此操作:

import pyxb
import Foo

def checkedAppendBar(rs, bar):
    rs.Bar.append(bar)
    bar = rs.Bar[-1]
    try:
        bar.validateBinding()
    except pyxb.ValidationError as e:
        print e.details()
    return bar

rs = Foo.ResultSet()
# Fails:
#bar = checkedAppendBar(rs, pyxb.BIND(name='a'))
bar = checkedAppendBar(rs, pyxb.BIND(name='a', code='42'))