你混淆了命名空间前缀 https://en.wikipedia.org/wiki/XML_namespace wp
与标签名称。命名空间前缀是命名空间 URI 的文档本地名称。wp:title
需要一个解析器来寻找xmlns:wp="..."
属性来查找名称空间本身(通常是 URL,但任何全局唯一的字符串都可以),无论是在标签本身还是在父标签上。这会将标签连接到唯一值,而不会使标签名称过于冗长而无法键入或阅读。
您需要提供名称空间,并且可以选择提供到元素创建者对象的名称空间映射(将短名称映射到完整名称空间名称)。默认E
提供的对象没有命名空间或命名空间映射集。我假设这里wp
is the http://wordpress.org/export/1.2/
Wordpress 命名空间,因为这似乎是最有可能的,尽管也可能是您正在尝试发送Windows Phone 通知 https://learn.microsoft.com/en-us/previous-versions/windows/apps/jj662933(v=vs.105).
而不是使用默认的E
元素制作者,创建你自己的ElementMaker
实例并传递给它一个namespace
诉说的论点lxml
该元素所属的 URL。为了在元素名称上获得正确的前缀,您还需要给它一个nsmap
将前缀映射到 URL 的字典:
from lxml.builder import ElementMaker
namespaces = {"wp": "http://wordpress.org/export/1.2/"}
E = ElementMaker(namespace=namespaces["wp"], nsmap=namespaces)
title = E.title("Value of the wp:title tag")
这会生成一个具有正确前缀的标签,and the xmlns:wp
属性:
>>> from lxml.builder import ElementMaker
>>> namespaces = {"wp": "http://wordpress.org/export/1.2/"}
>>> E = ElementMaker(namespace=namespaces["wp"], nsmap=namespaces)
>>> title = E.title("Value of the wp:title tag")
>>> etree.tostring(title, encoding="unicode")
'<wp:title xmlns:wp="http://wordpress.org/export/1.2/">Value of the wp:title tag</wp:title>'
您可以省略nsmap
值,但是你想在parent文档的元素。在这种情况下,您可能想要单独制作ElementMaker
您需要支持的每个名称空间的对象,然后将nsmap
最外层元素上的命名空间映射。写出文件时,lxml
然后自始至终都使用简称。
例如,创建一个WordPress WXR 格式文档 https://stackoverflow.com/questions/9356099/wordpress-wxr-specification需要多个命名空间:
from lxml.builder import ElementMaker
namespaces = {
"excerpt": "https://wordpress.org/export/1.2/excerpt/",
"content": "http://purl.org/rss/1.0/modules/content/",
"wfw": "http://wellformedweb.org/CommentAPI/",
"dc": "http://purl.org/dc/elements/1.1/",
"wp": "https://wordpress.org/export/1.2/",
}
RootElement = ElementMaker(nsmap=namespaces)
ExcerptElement = ElementMaker(namespace=namespaces["excerpt"])
ContentElement = ElementMaker(namespace=namespaces["content"])
CommentElement = ElementMaker(namespace=namespaces["wfw"])
DublinCoreElement = ElementMaker(namespace=namespaces["dc"])
ExportElement = ElementMaker(namespace=namespaces["wp"])
然后你会构建一个文档
doc = RootElement.rss(
RootElement.channel(
ExportElement.wxr_version("1.2"),
# etc. ...
),
version="2.0"
)
当漂亮地印刷时etree.tostring(doc, pretty_print=True, encoding="unicode")
,产生:
<rss xmlns:excerpt="https://wordpress.org/export/1.2/excerpt/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="https://wordpress.org/export/1.2/" version="2.0">
<channel>
<wp:wxr_version>1.2</wp:wxr_version>
</channel>
</rss>
注意如何仅根<rss>
元素有xmlns
属性,以及如何<wp:wxr_version>
标签使用正确的前缀,即使我们只给它命名空间 URI。
举一个不同的例子,如果您正在构建 Windows Phone 磁贴通知,那么它会更简单。毕竟,只有一个命名空间可供使用:
from lxml.builder import ElementMaker
namespaces = {"wp": "WPNotification"}
E = ElementMaker(namespace=namespaces["wp"], nsmap=namespaces)
notification = E.Notification(
E.Tile(
E.BackgroundImage("https://example.com/someimage.png"),
E.Count("42"),
E.Title("The notification title"),
# ...
)
)
产生
<wp:Notification xmlns:wp="WPNotification">
<wp:Tile>
<wp:BackgroundImage>https://example.com/someimage.png</wp:BackgroundImage>
<wp:Count>42</wp:Count>
<wp:Title>The notification title</wp:Title>
</wp:Tile>
</wp:Notification>
只有最外面的元素,<wp:Notification>
,现在有xmlns:wp
属性。所有其他元素只需要包括wp:
prefix.
请注意,使用的前缀是完全取决于你乃至optional。命名空间 URI 是跨不同 XML 文档唯一标识元素的真正关键。如果你用过E = ElementMaker(namespace="WPNotification", nsmap={None: "WPNotification"})
相反,因此产生了一个顶级元素<Notification xmlns="WPNotification">
您仍然拥有一个完全合法的 XML 文档,根据 XML 标准,该文档具有完全相同的含义。