2

这是使用 ElementTree 修改 XML的问题

我现在在我的 XML 中有名称空间,并尝试通过“ElementTree”在 Python 中使用名称空间解析 XML 中的答案并获得以下信息。

XML 文件。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <grandParent>
  <parent>
   <child>Sam/Astronaut</child>
  </parent>
 </grandParent>
</project>

在通过“ElementTree”查看使用 Python 中的命名空间解析 XML之后,我的 Python 代码

import xml.etree.ElementTree as ET

spaces='xmlns':'http://maven.apache.org/POM/4.0.0','schemaLocation':'http://maven.apache.org/xsd/maven-4.0.0.xsd'}

tree = ET.parse("test.xml")
a=tree.find('parent')          
for b in a.findall('child', namespaces=spaces):
 if b.text.strip()=='Jay/Doctor':
    print "child exists"
    break
else:
    ET.SubElement(a,'child').text="Jay/Doctor"

tree.write("test.xml")

我得到错误:AttributeError:'NoneType'对象没有属性'findall'

4

1 回答 1

2

这条线有两个问题:

a=tree.find('parent')          

首先,<parent>不是根元素的直接子元素。<parent>是根元素的孙子。到父级的路径看起来像/project/grandparent/parent。要搜索<parent>,请尝试 XPath 表达式*/parent或可能//parent

其次,<parent>存在于默认命名空间中,因此您无法.find()仅使用其简单名称来获取它。您需要添加命名空间。

下面是对 的两个同样有效的调用tree.find(),每个调用都应该找到<parent>节点:

a=tree.find('*/{http://maven.apache.org/POM/4.0.0}parent')
a=tree.find('*/xmlns:parent', namespaces=spaces)

接下来,调用findall()需要一个命名空间限定符:

for b in a.findall('xmlns:child', namespaces=spaces) 

第四,创建新子元素的调用需要命名空间限定符。可能有一种方法可以使用快捷方式名称,但我找不到。我不得不使用名字的长形式。

ET.SubElement(a,'{http://maven.apache.org/POM/4.0.0}child').text="Jay/Doctor"

最后,除非您提供默认命名空间,否则您的 XML 输出看起来会很丑:

tree.write('test.xml', default_namespace=spaces['xmlns'])

与 XML 方面无关,您错误地从上一个问题中复制了我的答案。与else对齐for,而不是与if

for ...
  if ...
else ...
于 2014-07-31T23:16:41.820 回答