如何用LXML写命名空间元素属性?

18 投票
2 回答
13563 浏览
提问于 2025-04-17 03:58

我正在使用 lxml (2.2.8) 来创建和写出一些 XML(具体来说是 XGMML)。将要读取这些 XML 的应用程序显然对格式要求比较严格,它希望看到一个顶层元素,里面包含:

<graph label="Test" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="h
ttp://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-
ns#" xmlns:cy="http://www.cytoscape.org" xmlns="http://www.cs.rpi.edu/XGMML"  di
rected="1">

我该如何用 lxml 设置这些 xmlns: 属性呢?如果我尝试一些明显的方法,

root.attrib['xmlns:dc']='http://purl.org/dc/elements/1.1/'
root.attrib['xmlns:xlink']='http://www.w3.org/1999/xlink'
root.attrib['xmlns:rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
root.attrib['xmlns:cy']='http://www.cytoscape.org'
root.attrib['xmlns']='http://www.cs.rpi.edu/XGMML'

lxml 会抛出一个错误:ValueError: Invalid attribute name u'xmlns:dc'

我以前在简单的项目中使用过 XML 和 lxml,但到现在为止一直没有碰到过需要了解命名空间的情况。

2 个回答

6

使用 ElementMaker:

import lxml.etree as ET
import lxml.builder as builder
E = builder.ElementMaker(namespace='http://www.cs.rpi.edu/XGMML',
                         nsmap={None: 'http://www.cs.rpi.edu/XGMML',
                         'dc': 'http://purl.org/dc/elements/1.1/',
                         'xlink': 'http://www.w3.org/1999/xlink',
                         'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
                         'cy': 'http://www.cytoscape.org', })
graph = E.graph(label="Test", directed="1")
print(ET.tostring(graph, pretty_print=True))

会产生

<graph xmlns:cy="http://www.cytoscape.org" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.cs.rpi.edu/XGMML" directed="1" label="Test"/>
29

跟其他一些工具,比如ElementTree或者其他序列化工具不同,lxml需要你提前设置好这些命名空间:

NSMAP = {"dc" : 'http://purl.org/dc/elements/1.1',
         "xlink" : 'http://www.w3.org/1999/xlink'}

root = Element("graph", nsmap = NSMAP)

(接下来还需要为其他声明做类似的设置)

然后你就可以用这些命名空间,按照它们的正确声明来使用:

n = SubElement(root, "{http://purl.org/dc/elements/1.1}foo")

当然,这样输入起来会很麻烦,所以通常建议把路径赋值给一些简短的常量名:

DCNS = "http://purl.org/dc/elements/1.1"

然后在NSMAPSubElement的声明中都使用这个变量:

n = SubElement(root, "{%s}foo" % (DCNS))

撰写回答