python lxml 我如何在项目名称中使用标签?

Luc*_*aga 1 python xml wordpress lxml python-3.x

我需要使用项目的特殊名称构建 xml 文件,这是我当前的代码:

from lxml import etree
import lxml
from lxml.builder import E

wp = E.wp

tmp = wp("title")

print(etree.tostring(tmp))
Run Code Online (Sandbox Code Playgroud)

当前输出是这样的:

b'<wp>title</wp>'
Run Code Online (Sandbox Code Playgroud)

我想成为 :

b'<wp:title>title</title:wp>'
Run Code Online (Sandbox Code Playgroud)

我如何创建具有如下名称的项目:wp:title

Mar*_*ers 7

您将命名空间前缀 wp与标签名称混淆了。命名空间前缀是命名空间 URI 的文档本地名称。需要解析器在标签本身或父标签上wp:title查找属性来查找名称空间本身(通常是 URL,但任何全局唯一字符串都可以)。xmlns:wp="..."这会将标签连接到唯一值,而不会使标签名称过于冗长而无法键入或阅读。

您需要提供名称空间,并且可以选择提供到元素创建者对象的名称空间映射(将短名称映射到完整名称空间名称)。提供的默认E对象没有命名空间或命名空间映射集。我将假设这里wphttp://wordpress.org/export/1.2/Wordpress 命名空间,因为这似乎是最有可能的,尽管您也可能正在尝试发送Windows Phone 通知

不要使用默认的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")
Run Code Online (Sandbox Code Playgroud)

这会生成一个具有正确前缀属性的标签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")
Run Code Online (Sandbox Code Playgroud)

您可以省略该nsmap值,但您希望在文档的父元素上有这样的映射。在这种情况下,您可能希望ElementMaker为需要支持的每个命名空间创建单独的对象,并将nsmap命名空间映射放在最外层的元素上。写出文档时,lxml请自始至终使用简称。

例如,创建Wordpress WXR 格式文档将需要多个命名空间:

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"])
Run Code Online (Sandbox Code Playgroud)

然后你会构建一个文档

doc = RootElement.rss(
    RootElement.channel(
        ExportElement.wxr_version("1.2"),
        # etc. ...
    ),
    version="2.0"
)
Run Code Online (Sandbox Code Playgroud)

当用 漂亮地打印时etree.tostring(doc, pretty_print=True, encoding="unicode"),会产生:

>>> 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>'
Run Code Online (Sandbox Code Playgroud)

请注意,只有根<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"),
        # ...
    )
)
Run Code Online (Sandbox Code Playgroud)

产生

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"])
Run Code Online (Sandbox Code Playgroud)

现在只有最外面的元素<wp:Notification>具有该xmlns:wp属性。所有其他元素只需要包含wp:前缀。

请注意,使用的前缀完全取决于您,甚至是可选的。命名空间 URI 是跨不同 XML 文档唯一标识元素的真正关键。如果您E = ElementMaker(namespace="WPNotification", nsmap={None: "WPNotification"})改为使用,并因此生成了一个顶级元素,那么<Notification xmlns="WPNotification">您仍然拥有一个完全合法的 XML 文档,根据 XML 标准,该文档具有完全相同的含义。