两行阻止使用 Python 到达特定的 XML 节点

Two lines prevent reaching to a specific XML node using Python

要到达 python 中的特定节点,我会做这样的事情 nodeZ = xmlDoc.find("X/Y/Z") 这对我来说效果很好。

但是,当我在 XML 文件的 beginning 处有 following two lines 时,我无法到 select 或再到达节点。 我该怎么办?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE raml SYSTEM 'raml20.dtd'>

顺便说一句,我正在加载 lxml 包

更新:一个真实的例子

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE raml SYSTEM 'raml20.dtd'>
<raml version="2.0" xmlns="raml20.xsd">
  <cmData type="actual">
    <header>
      <log dateTime="2015-10-13T15:57:06" action="created" appInfo="ActualExporter">InternalValues are used</log>
    </header>
    <managedObject class="MRBTS" version="XXX" distName="PLMN-PLMN/MRBTS-XXX" id="111">
    </managedObject>
  </cmData>
</raml>

我尝试通过以下方式访问 managedObject 节点:

from lxml import etree
xmlDoc = etree.parse("D:/File.xml")
moNode = xmlDoc.find("cmData/managedObject")

正如我上面提到的,只有删除前两行才能正常工作。

尝试:

from lxml import etree, html

text = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE raml SYSTEM 'raml20.dtd'>
<raml version="2.0" xmlns="raml20.xsd">
  <cmData type="actual">
    <header>
      <log dateTime="2015-10-13T15:57:06" action="created" appInfo="ActualExporter">InternalValues are used</log>
    </header>
    <managedObject class="MRBTS" version="XXX" distName="PLMN-PLMN/MRBTS-XXX" id="111">
    </managedObject>
  </cmData>
</raml>"""

html_code = etree.HTML(text)
result = etree.tostring(html_code, pretty_print=True, method="html")
tree = html.fromstring(result)

data = tree.xpath('//raml/cmdata/managedobject')[0]

managed_object_class = data.xpath('@class')[0]
managed_object_version = data.xpath('@version')[0]
managed_object_distname = data.xpath('@distname')[0]
managed_object_id = data.xpath('@id')[0]

print "Id: {}".format(managed_object_id)
print "Class: {}".format(managed_object_class)
print "Version: {}".format(managed_object_version)
print "DistName: {}".format(managed_object_distname)

输出:

Id: 111
Class: MRBTS
Version: XXX
DistName: PLMN-PLMN/MRBTS-XXX

我无法重现问题。前两行(XML 声明和文档类型声明)是否存在并不重要。根本找不到元素。

重要的是 XML 文档在命名空间中。命名空间名称 (raml20.xsd) 有点不寻常,但没关系。下面打印出想要的元素:

from lxml import etree

xmlDoc = etree.parse("File.xml")
moNode = xmlDoc.find("r:cmData/r:managedObject", namespaces={"r": "raml20.xsd"})
print moNode

在上面的代码中,使用了一个前缀(r)。另一种方法是直接使用命名空间名称(用大括号括起来):

moNode = xmlDoc.find("{raml20.xsd}cmData/{raml20.xsd}managedObject")

通配符也有效:

moNode = xmlDoc.find("{*}cmData/{*}managedObject")

在这三种情况下,输出都是这样的:

<Element {raml20.xsd}managedObject at 0x2787c60>

更多信息:http://lxml.de/tutorial.html#namespaces.