【问题标题】:python lxml how i use tag in items name?python lxml我如何在项目名称中使用标签?
【发布时间】:2019-09-27 15:16:54
【问题描述】:

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

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

wp = E.wp

tmp = wp("title")

print(etree.tostring(tmp))

当前输出是这样的:

b'<wp>title</wp>'

我想成为:

b'<wp:title>title</title:wp>'

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

【问题讨论】:

  • 如果这是您的整个 XML,则它不是合法的 XML,因为开始和结束标记必须匹配,并且需要定义以冒号分隔的命名空间前缀 (wp),例如使用 xmlns:wp=...

标签: python xml python-3.x wordpress lxml


【解决方案1】:

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

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

不要使用默认的E 元素制造商,而是创建自己的ElementMaker 实例并传递一个namespace 参数来告诉lxml 该元素属于哪个URL。要在元素名称上获得正确的前缀,您还需要为其提供一个将前缀映射到 URL 的 nsmap 字典:

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")

这会产生一个带有正确前缀的标签,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 值,但您会希望在文档的 元素上有这样的映射。在这种情况下,您可能希望为需要支持的每个命名空间创建单独的 ElementMaker 对象,并将 nsmap 命名空间映射放在最外层元素上。在写出文档时,lxml 会在整个过程中使用短名称。

例如,创建Wordpress WXR format document 将需要多个命名空间:

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>

注意只有根 &lt;rss&gt; 元素有 xmlns 属性,以及 &lt;wp:wxr_version&gt; 标记如何使用正确的前缀,即使我们只给它命名空间 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>

现在只有最外层元素&lt;wp:Notification&gt; 具有xmlns:wp 属性。所有其他元素只需要包含wp: 前缀即可。

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

【讨论】:

  • 这个答案很棒而且非常有用。谢谢你,感谢 CodeMentor 的帮助,@MartijnPieters!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
  • 2012-04-22
  • 1970-01-01
  • 2020-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多