使用PYXB解析XML。无法获取嵌套的匿名元素

0 投票
1 回答
2385 浏览
提问于 2025-04-18 03:39

我使用PYXB(pyxbgen)为以下的xsd文件创建了Python绑定,使用的命令如下:

pyxbgen -u Event.xsd -m Event
pyxbgen -u Shape.xsd -m Shape
pyxbgen -u flow-tags.xsd -m flow-tags

通过生成的绑定,我可以访问所有的“事件”数据,但我不知道怎么访问“细节”元素和数据。具体来说,就是形状元素中的椭圆和多边形(带有顶点数据)。细节元素是一个匿名类型。

这是我目前写的代码:

    import Shape, Event, flow-tags

    xml = '''
    <event how="h-p" opex="e-TEST" qos="7-r-g" stale="2014-04-21T20:50:01.85Z" start="2014-04-21T20:48:01.85Z" time="2014-04-21T20:48:01.85Z" type="a-n-A-M-F-R-Z" uid="6716" version="2.0"><detail><_flow-tags_ debug="2014-04-21T20:48:01.00Z" /><shape><ellipse angle="33" major="44" minor="22" /><polyline closed="1"><vertex hae="1" lat="44" lon="-77" /></polyline></shape></detail><point ce="122.8" hae="817.2" lat="42.5612194" le="431.3" lon="-71.302077" /></event>
    '''

    event = Event.CreateFromDocument(xml)
    print event.uid
    print event.point.lon

    detail = event.detail
    #not sure what goes after this to get content of detail data?????

以下是我使用的Event.xsd和Shape.xsd文件。它们不是我的,所以如果文件有问题,我无法进行修改。

Event.xsd:

 <?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified">
    <xs:element name="event">
        <xs:annotation>
            <xs:documentation>Event Definition</xs:documentation>
        </xs:annotation>
        <xs:complexType>
        <xs:all>
            <xs:element ref="point" />
            <xs:element ref="detail" minOccurs="0" />
        </xs:all>
        <xs:attribute name="version" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:decimal">
                    <xs:minInclusive value="2" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="type" use="required">
            <xs:annotation>
                <xs:documentation>
                    The "type" attribute
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="\w+(-\w+)*(;[^;]*)?" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="access" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    The access field
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="qos" use="optional">
            <xs:annotation>
                <xs:documentation>
                    format - digit-character-character
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="\d-\w-\w" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="opex" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    The opex field
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="uid" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    The "uid" attribute
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="time" type="xs:dateTime" use="required">
            <xs:annotation>
                <xs:documentation>
                    The XML schema includes three time values:
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="start" type="xs:dateTime" use="required">
            <xs:annotation>
                <xs:documentation>
                    format - DTG
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="stale" type="xs:dateTime" use="required">
            <xs:annotation>
                <xs:documentation>
                    The "stale" attribute
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="how" use="required">
            <xs:annotation>
                <xs:documentation>
                    format = character-character
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:pattern value="\w(-\w+)*" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>
<xs:element name="detail">
    <xs:annotation>
        <xs:documentation>
            format
        </xs:documentation>
    </xs:annotation>
    <xs:complexType>
        <xs:sequence>
            <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:anyAttribute processContents="skip" />
    </xs:complexType>
</xs:element>
<xs:element name="point">
    <xs:complexType>
        <xs:attribute name="lat" use="required">
            <xs:annotation>
                <xs:documentation>Latitude based on WGS-84 ellipsoid in signed
                    degree-decimal format (e.g. -33.350000). Range -90 -> +90.
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:decimal">
                    <xs:minInclusive value="-90" />
                    <xs:maxInclusive value="90" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="lon" use="required">
            <xs:annotation>
                <xs:documentation>Longitude based on WGS-84 ellipsoid in signed
                    degree-decimal format (e.g. 44.383333). Range -180 -> +180.
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:decimal">
                    <xs:minInclusive value="-180" />
                    <xs:maxInclusive value="180" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="hae" type="xs:decimal" use="required">
            <xs:annotation>
                <xs:documentation>HAE acronym for Height above Ellipsoid based on
                    WGS-84 ellipsoid (measured in meters).
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="ce" type="xs:decimal" use="required">
            <xs:annotation>
                <xs:documentation>
                    Circular Error
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="le" type="xs:decimal" use="required">
            <xs:annotation>
                <xs:documentation>
                    Linear Error
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
</xs:element>

Shape.xsd:

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.w3.org/2001/XMLSchema      http://www.w3.org/2001/XMLSchema.xsd"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="nonNegativeDecimal">
    <xs:restriction base="xs:decimal">
        <xs:minInclusive value="0" />
    </xs:restriction>
    <!-- Defined as global type for XML Gallery manifest reference than 
        any other reason -->
</xs:simpleType>
<xs:element name="shape">
    <xs:annotation>
        <xs:documentation></xs:documentation>
    </xs:annotation>
    <xs:complexType>
        <xs:sequence>
            <xs:element name="ellipse" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>The "ellipse" is a common shape abstraction used
                        by many geomanipulation applications; it is supported natively.
                    </xs:documentation>
                </xs:annotation>
                <xs:complexType>
                    <xs:sequence>
                        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
                    </xs:sequence>
                    <xs:attribute name="major" type="nonNegativeDecimal"
                        use="required">
                        <xs:annotation>
                            <xs:documentation>Ellipse major axis (meters)</xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                    <xs:attribute name="minor" type="nonNegativeDecimal"
                        use="required">
                        <xs:annotation>
                            <xs:documentation>Ellipse minor axis (meters)</xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                    <xs:attribute name="angle" type="xs:decimal" use="required">
                        <xs:annotation>
                            <xs:documentation>Orientation of major axis with respect to true
                                north.
                            </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                    <xs:attribute name="level" type="xs:integer" use="optional">
                        <xs:annotation>
                            <xs:documentation>"level"
                            </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                    <xs:attribute name="extrude" type="xs:nonNegativeInteger"
                        use="optional">
                        <xs:annotation>
                            <xs:documentation>A "Height" of the ellipse used to make the
                                flat object encompas a volume.
                            </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                </xs:complexType>
            </xs:element>
            <xs:element name="polyline" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>The poly line provides a mechanism to express
                        arbitrarily complex two-dimenstional shapes.
                    </xs:documentation>
                </xs:annotation>
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="vertex" minOccurs="2" maxOccurs="unbounded">
                            <xs:complexType>
                                <xs:attribute name="lat" use="required">
                                    <xs:annotation>
                                        <xs:documentation>Latitude based on WGS-84 ellipsoid in
                                            signed degree-decimal format (e.g. -33.350000). Range -90 ->
                                            +90. Positive values denote north.
                                        </xs:documentation>
                                    </xs:annotation>
                                    <xs:simpleType>
                                        <xs:restriction base="xs:decimal">
                                            <xs:minInclusive value="-90" />
                                            <xs:maxInclusive value="90" />
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:attribute>
                                <xs:attribute name="lon" use="required">
                                    <xs:annotation>
                                        <xs:documentation>Longitude based on WGS-84 ellipsoid in
                                            signed degree-decimal format (e.g. 44.383333). Range -180 ->
                                            +180. Positive values denote east.
                                        </xs:documentation>
                                    </xs:annotation>
                                    <xs:simpleType>
                                        <xs:restriction base="xs:decimal">
                                            <xs:minInclusive value="-180" />
                                            <xs:maxInclusive value="180" />
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:attribute>
                                <xs:attribute name="hae" type="xs:decimal" use="optional">
                                    <xs:annotation>
                                        <xs:documentation>Height Above Ellipsoid (HAE) in Meters.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:attribute>
                            </xs:complexType>
                        </xs:element>
                        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
                    </xs:sequence>
                    <xs:attribute name="level" type="xs:integer">
                        <xs:annotation>
                            <xs:documentation>"level"
                            </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                    <xs:attribute name="closed" type="xs:boolean"
                        default="true">
                        <xs:annotation>
                            <xs:documentation>True if the list of verticies should be
                                considered a closed polygon (an implicit line will be added
                                from vertex N to vertex 0).
                            </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                </xs:complexType>
            </xs:element>
            <xs:element name="dxf" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>This is a hook for an arbitrary 3D DXF
                        description of a volume of space.
                    </xs:documentation>
                </xs:annotation>
                <xs:complexType>
                    <xs:sequence>
                        <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
                    </xs:sequence>
                    <xs:attribute name="level" type="xs:integer">
                        <xs:annotation>
                            <xs:documentation>"level"  </xs:documentation>
                        </xs:annotation>
                    </xs:attribute>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="version" type="xs:decimal" use="optional">
            <xs:annotation>
                <xs:documentation>Version tag for this sub schema. Can be used to
                    ensure upward compatibility with future revisions.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
</xs:element>

flow-tags.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="_flow-tags_">
    <xs:annotation>
        <xs:documentation>This is a detail sub-schema</xs:documentation>
    </xs:annotation>
    <xs:complexType>
        <xs:sequence>
            <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:attribute name="version" type="xs:decimal" use="optional" />
        <xs:anyAttribute processContents="lax">
            <xs:annotation>
                <xs:documentation>A system-specific flowtag identifier.
                </xs:documentation>
            </xs:annotation>
        </xs:anyAttribute>
    </xs:complexType>
</xs:element>

非常感谢任何帮助!

1 个回答

2

在details元素中,如果有一些子元素不被识别,它们会被当作通配符添加,可以这样访问:

detail = event.detail
for elt in detail.wildcardElements():
    print elt

不过,这些元素都是DOM实例(一个是_flow-tags_,一个是shape)。通常情况下,PyXB会把已经加载到应用程序中的元素转换为绑定,但它们仍然会存储在wildcardElements()数组中。这里没有发生这种情况,因为你使用的两个模式都没有命名空间,但被当作独立的模式来处理。在这两个模式中都没有元素_flow-tags_,而shape没有被转换为绑定,因为来自Shape模式的元素在Event使用的缺失命名空间中无法被识别。

由于我不知道这些模式是从哪里来的,所以我不能确定它们应该如何使用,但一种方法是把它们合并成一个父模式,如下所示:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="Shape.xsd"/>
<xs:include schemaLocation="Event.xsd"/>
</xs:schema>

然后从这个模式构建绑定:

pyxbgen -u combine.xsd -m combine

接着你可以这样导入这些绑定,它们包含了Event和Shape组件:

import pyxb
import combine

xml = '''
<event how="h-p" opex="e-TEST" qos="7-r-g" stale="2014-04-21T20:50:01.85Z" start="2014-04-21T20:48:01.85Z" time="2014-04-21T20:48:01.85Z" type="a-n-A-M-F-R-Z" uid="6716" version="2.0"><detail><_flow-tags_ debug="2014-04-21T20:48:01.00Z" /><shape><ellipse angle="33" major="44" minor="22" /><polyline closed="1"><vertex hae="1" lat="44" lon="-77" /></polyline></shape></detail><point ce="122.8" hae="817.2" lat="42.5612194" le="431.3" lon="-71.302077" /></event>
'''

try:
    event = combine.CreateFromDocument(xml)
except pyxb.IncompleteElementContentError as ex:
    print ex.details()

你会发现这个示例文档是无效的,原因是出现了以下错误:

The containing element polyline is defined at Shape.xsd[65:12].
The containing element type <class 'combine.CTD_ANON_2'> is defined at Shape.xsd[71:16]
The <class 'combine.CTD_ANON_2'> automaton is not in an accepting state.
Any accepted content has been stored in instance
The following element and wildcard content would be accepted:
        An element vertex per Shape.xsd[73:24]
No content remains unconsumed

如果你查看Shape.xsd的第73行,你会看到一个多边形线需要至少两个顶点元素。如果你把文档修正为有第二个顶点,那么details.wildcardElements()的第一个成员仍然是一个DOM元素实例,但第二个将是一个shape绑定。

撰写回答