如何使用 lxml 在属性值中设置命名空间前缀?

Posted

技术标签:

【中文标题】如何使用 lxml 在属性值中设置命名空间前缀?【英文标题】:how to set a namespace prefix in an attribute value using the lxml? 【发布时间】:2010-09-10 14:24:05 【问题描述】:

我正在尝试使用 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: 放在 value 之前,但我认为它可以做得更好。

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)

可以写得更好吗?

【问题讨论】:

【参考方案1】:

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

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

为您创建的每个元素添加带有“xs”前缀的nsmap;或 使用_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)

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

【讨论】:

以上是关于如何使用 lxml 在属性值中设置命名空间前缀?的主要内容,如果未能解决你的问题,请参考以下文章

如何用前缀替换 xmlns 命名空间属性?

如何将注册中设置的值显示到 seevalue() 函数中?范围

如何从 lxml 树中剥离命名空间?

XML名命空间

如何在 SwiftUI 中嵌入 ForEach 的 HStack 中设置相对宽度?

Atitit xml命名空间机制