如何给lxml中的节点属性添加不同的命名空间

How to add different namespaces to node attributes in lxml

我正在使用 lxml 生成一个 XML 文件,如下所示。 Whosebug 上的 documentation and other questions (1, ) 将我推向了正确的方向。我正在努力解决的是名称空间前缀,例如 markListmark 节点中的前缀。

<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE paula SYSTEM "paula_mark.dtd">
<paula version="1.1">
    <header paula_id="Layer_Annotation.0_0000.mark"/>
    <markList xmlns:xlink="http://www.w3.org/1999/xlink" type="Annotation" xml:base="text.xml">
        <!--foo-->
        <mark id="span1" xlink:href="#sTok1"/>
        <!--bar-->
        <mark id="span2" xlink:href="#sTok2"/>
    </markList>
</paula>

这就是我到目前为止所得到的。正如您从下面的输出中看到的,我卡在了 markList 节点,并且已经为此苦苦思索了一段时间。任何进一步的推动将不胜感激。

from lxml import etree

class XMLNamespaces:
   xlink = "http://www.w3.org/1999/xlink"
   xml = "text.xml"

top = etree.Element("paula", {"version":"1.1"})
header = etree.SubElement(top, "header", {"paula_id": "annotation.mark"})
mark_list = etree.SubElement(top, "markList", {
    etree.QName(XMLNamespaces.xlink, "xlink"): "http://www.w3.org/1999/xlink",
    "type": "Annotation",
    etree.QName(XMLNamespaces.xml, "xml"): "http://www.w3.org/1999/xlink",
})

body = etree.SubElement(top, "body")    
body.text = "test body"
    
print(etree.tounicode(top, pretty_print=True))

这是我当前的输出:

<paula version="1.1">
  <header paula_id="annotation.mark"/>
  <markList xmlns:ns0="http://www.w3.org/1999/xlink" xmlns:ns1="text.xml" ns0:xlink="http://www.w3.org/1999/xlink" type="Annotation" ns1:xml="http://www.w3.org/1999/xlink"/>
  <body>test body</body>
</paula>

这里有一个方法:

from lxml import etree
 
class XMLNamespaces:
   xlink = "http://www.w3.org/1999/xlink"
   xml = "http://www.w3.org/XML/1998/namespace"
 
top = etree.Element("paula", {"version": "1.1"})
 
header = etree.SubElement(top, "header", {"paula_id": "annotation.mark"})
 
mark_list = etree.SubElement(top, "markList",
                             {"type": "Annotation",
                              etree.QName(XMLNamespaces.xml, "base"): "text.xml"},
                              nsmap={"xlink": XMLNamespaces.xlink})
 
mark = etree.SubElement(mark_list, "mark",
                        {"id": "span1",  
                         etree.QName(XMLNamespaces.xlink, "href"): "#sTok1"})
 
mark = etree.SubElement(mark_list, "mark",
                        {"id": "span2",  
                         etree.QName(XMLNamespaces.xlink, "href"): "#sTok2"})
    
print(etree.tounicode(top, pretty_print=True))

输出:

<paula version="1.1">
  <header paula_id="annotation.mark"/>
  <markList xmlns:xlink="http://www.w3.org/1999/xlink" type="Annotation" xml:base="text.xml">
    <mark id="span1" xlink:href="#sTok1"/>
    <mark id="span2" xlink:href="#sTok2"/>
  </markList>
</paula>

评论:

    markList 子元素上的
  • nsmap={"xlink": XMLNamespaces.xlink}) 确保在输出中使用 xlink 而不是 ns0
  • xml 前缀的 URI 是 http://www.w3.org/XML/1998/namespace。这个 URI 有点特殊,因为它不需要出现在 XML 文件中,但它必须在 Python 代码中使用。