3

我正在尝试使用 lxml 创建 XML 模式。一开始是这样的:

<xs:schema xmlns="http://www.goo.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"         elementFormDefault="qualified" targetNamespace="http://www.goo.com">
  <xs:element type="xs:string" name="name"/>
  <xs:element type="xs:positiveInteger" name="age"/>
</xs:schema>

我已经这样做了 - 通过将 xs: 放在价值之前,但我认为它可以做得更好。

def schema():
    SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
    XS = "{%s}" % SCHEMA_NAMESPACE
    NSMAP = {None: "http://www.goo.com"}

    schema = etree.Element(XS+"schema",
                           nsmap = NSMAP,
                           targetNamespace="http://www.goo.com",
                           elementFormDefault="qualified")

    element = etree.Element(XS+"element", 
                            attrib = {"name" : "name",
                                      "type" : "xs:string"})
    schema.append(element)
    element = etree.Element(XS+"element", 
                            attrib = {"name" : "age",
                                      "type" : "xs:positiveInteger"})

    schema.append(element)
    return etree.tostring(schema, pretty_print=True)

它可以写得更好吗?

4

1 回答 1

2

"xs": SCHEMA_NAMESPACE顺便说一句,您需要在您的 NSMAP中包含或这样的内容——否则您生成的 XML 中的任何内容实际上都不会将“xs”前缀映射到正确的命名空间。这也将允许您只指定带有前缀的元素名称;例如“xs:元素”。

至于您的主要问题,我认为这可能很好,只要您始终在任何地方使用相同的前缀到命名空间映射,例如使用全局NSMAP. 如果您正在处理可能具有任意命名空间前缀的 XML,请确保:

  • nsmap为您创建的每个元素添加“xs”前缀;或者
  • 使用_Element.nsmap属性获取父属性的命名空间映射,将其反转,并在反转映射中查找适当的前缀。

后者的一个例子:

SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema"

def add_element(schema):
    nsmap = schema.nsmap
    nsrmap = dict([(uri, prefix) for prefix, uri in nsmap.items()])
    prefix = nsrmap[SCHEMA_NAMESPACE]
    xs = lambda name: "%s:%s" % (prefix, name)
    element = schema.makeelement(xs("element"), nsmap=nsmap,
                                 attrib={'name': 'age', 'type': xs('string')})
    schema.append(element)
    return etree.tostring(schema, pretty_print=True)

但这对于大多数情况来说可能是矫枉过正。

于 2010-09-10T15:59:22.940 回答