我正在尝试从带有命名空间xmlns:v="urn:schemas-microsoft-com:vml"
<v:imagedata r:id="rId7" o:title="1-REN"/>
的 Word 文档中查找所有内容,但我无法弄清楚语法到底是什么。
文档只涵盖了非常简单的情况,并且加入了 URN 和 VML 组合,我似乎无法让我在网上看到的任何示例都起作用。有没有人碰巧知道它是什么?
我正在尝试做这样的事情:
namespace = {'v': "urn:schemas-microsoft-com:vml"}
results = ET.fromstring(xml).findall("imagedata", namespace)
for image_id in results:
print(image_id)
编辑:@aneroid写的是1000%的正确答案,超级有帮助。你应该对它投赞成票。也就是说,在了解了所有这些之后 - 我选择了 BS4 答案,因为它完全按照我的需要😂在两行中完成了整个工作。如果您实际上并不关心命名空间,那么似乎更容易。
在 Python 3.8 中使用 ElementTree,您可以简单地使用通配符 ({*}
( 作为命名空间:
results = ET.fromstring(xml).findall(".//{*}imagedata")
请注意.//
部分,这意味着搜索整个文档(所有后代(。
ET.findall()
vsBS4.find_all()
:
- 默认情况下,ElementTree 的
findall()
不是递归的*。它只会找到所提供节点的直接子节点。因此,在您的情况下,它只是直接在根元素下搜索图像节点。- *根据 MZJN 下面的评论,在
match
参数(标签或路径(前面加上".//"
将在树中的任何位置搜索该节点,因为它支持 XPath。
- *根据 MZJN 下面的评论,在
- 美丽汤的
find_all()
搜索所有后代。因此,它可以在树中的任何位置找到"图像数据"节点。 -
但是,
ElementTree.iter()
确实会搜索所有后代。使用文档中的"使用命名空间"示例:>>> for char in root.iter('{http://characters.example.com}character'): ... print(' |-->', char.text) ... |--> Lancelot |--> Archie Leach |--> Sir Robin |--> Gunther |--> Commander Clement
- 可悲的是,
ET.iterfind()
将命名空间作为字典(如 ET.findall(使用,也不搜索后代,默认情况下只搜索直接子项*。就像ET.findall一样。除了如何处理标签中''
的空字符串在命名空间中,一个返回列表而另一个返回迭代器之外,我不能说ET.findall
和ET.iterfind
之间有有意义的区别。- *与上述
ET.findall()
一样,前缀".//"
使其搜索整个树(与任何节点匹配(。
- *与上述
当您将命名空间与 ET 一起使用时,您仍然需要带有标签的命名空间名称。结果行应为:
namespace = {'v': "urn:schemas-microsoft-com:vml"}
results = ET.fromstring(xml).findall("v:imagedata", namespace) # note the 'v:'
另外,'v'
不需要是'v'
,如果需要,您可以将其更改为更有意义的内容:
namespace = {'image': "urn:schemas-microsoft-com:vml"}
results = ET.fromstring(xml).findall("image:imagedata", namespace)
要获取树中任意位置的所有图像数据元素,请使用".//"
前缀:
results = ET.fromstring(xml).findall(".//v:imagedata", namespace)
我将保持这个问题悬而未决,但我目前使用的解决方法是使用 BeautifulSoup,它很乐意接受v:
语法。
soup = BeautifulSoup(xml, "lxml")
results = soup.find_all("v:imagedata")