我需要在Python中机器生成(不要解析!)一个(可能是复杂的)XML文件。
我(相对)熟悉xml和lxml模块,但我不清楚如何根据xsl规范生成有效的XML checked 。
我需要建立的是:
<?xml version='1.0' encoding='utf-8'?>
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uuid_id" version="2.0">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:identifier opf:scheme="calibre" id="calibre_id">4117</dc:identifier>
<dc:identifier opf:scheme="uuid" id="uuid_id">d06a2234-67b4-40db-8f4a-136e52057101</dc:identifier>
<dc:title>La Fine Di Alice</dc:title>
<dc:creator opf:file-as="Homes, A. M." opf:role="aut">A. M. Homes</dc:creator>
<dc:contributor opf:file-as="calibre" opf:role="bkp">calibre (3.10.0) [https://calibre-ebook.com]</dc:contributor>
<dc:date>2005-11-15T00:00:00+00:00</dc:date>
<dc:publisher>Minimum Fax</dc:publisher>
<dc:identifier opf:scheme="ISBN">9788875210649</dc:identifier>
<dc:language>en</dc:language>
<meta content="{"A. M. Homes": ""}" name="calibre:author_link_map"/>
<meta content="2017-11-07T07:34:41.217796+00:00" name="calibre:timestamp"/>
<meta content="La Fine Di Alice" name="calibre:title_sort"/>
</metadata>
<guide>
<reference href="cover.jpg" title="Cover" type="cover"/>
</guide>
</package>
完整的语法是here。
我尝试了一些事情:
from lxml import etree as ET
et = ET.Element('package', attrib={'version': "2.0", 'xmlns': "http://www.idpf.org/2007/opf", 'unique-identifier': "BookId"})
md = ET.SubElement(et, 'metadata', attrib={'xmlns:dc': "http://purl.org/dc/elements/1.1/", 'xmlns:opf': "http://www.idpf.org/2007/opf"})
au = ET.SubElement(md, 'dc:title')
au.text = bk['Title']
s = ET.tostring(et, pretty_print=True)
...但它失败了:“ValueError:无效的属性名称'xmlns:dc'”
任何指针欢迎。
答案 0 :(得分:2)
参考:http://lxml.de/tutorial.html#namespaces
您不能将命名空间指定为:
限定字符串。相反,您可以使用{http://url.url/url}tag
表单或QName
表单。
这是您的程序,使用名称空间:
from lxml import etree as ET
NS_DC = "http://purl.org/dc/elements/1.1/"
NS_OPF = "http://www.idpf.org/2007/opf"
nsmap = {
"dc": NS_DC,
None: NS_OPF,
}
PACKAGE = ET.QName(NS_OPF, 'package')
METADATA = ET.QName(NS_OPF, 'metadata')
TITLE = ET.QName(NS_DC, 'title')
et = ET.Element(PACKAGE,
attrib={'version': "2.0",
'unique-identifier': "BookId"},
nsmap=nsmap)
md = ET.SubElement(et, METADATA)
au = ET.SubElement(md, TITLE)
au.text = "A Tale of Two Cities"
s = ET.tostring(et, pretty_print=True)
print(s.decode('utf-8'))
您可以选择使用lxml.builder.ElementMaker
。这是一个创建示例的一部分的程序。
注意:
dict
来表示非有效Python名称的属性名称。 QName
表示名称空间限定名称。validator
验证生成的树。
from lxml import etree as ET
from lxml.builder import ElementMaker
NS_DC = "http://purl.org/dc/elements/1.1/"
NS_OPF = "http://www.idpf.org/2007/opf"
SCHEME = ET.QName(NS_OPF, 'scheme')
FILE_AS = ET.QName(NS_OPF, "file-as")
ROLE = ET.QName(NS_OPF, "role")
opf = ElementMaker(namespace=NS_OPF, nsmap={"opf": NS_OPF, "dc": NS_DC})
dc = ElementMaker(namespace=NS_DC)
validator = ET.RelaxNG(ET.parse("opf-schema.xml"))
tree = (
opf.package(
{"unique-identifier": "uuid_id", "version": "2.0"},
opf.metadata(
dc.identifier(
{SCHEME: "uuid", "id": "uuid_id"},
"d06a2234-67b4-40db-8f4a-136e52057101"),
dc.creator({FILE_AS: "Homes, A. M.", ROLE: "aut"}, "A. M. Homes"),
dc.title("My Book"),
dc.language("en"),
),
opf.manifest(
opf.item({"id": "foo", "href": "foo.pdf", "media-type": "foo"})
),
opf.spine(
{"toc": "uuid_id"},
opf.itemref({"idref": "uuid_id"}),
),
opf.guide(
opf.reference(
{"href": "cover.jpg", "title": "Cover", "type": "cover"})
),
)
)
validator.assertValid(tree)
print(ET.tostring(tree, pretty_print=True).decode('utf-8'))