如何使用Python XML findall查找'<v:imagedata r:id="rId7&quo



我正在尝试从带有命名空间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。
  • 美丽汤的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.findallET.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)

当然,如果它们不是根的直接子元素,这仍然不一定会让你获得所有的 imagedata 元素。为此,您需要创建一个递归函数来为您执行此操作。请参阅SO上的此答案,了解如何操作。请注意,虽然该答案进行了递归搜索,但如果后代深度太...

要获取树中任意位置的所有图像数据元素,请使用".//"前缀:

results = ET.fromstring(xml).findall(".//v:imagedata", namespace)

我将保持这个问题悬而未决,但我目前使用的解决方法是使用 BeautifulSoup,它很乐意接受v:语法。

soup = BeautifulSoup(xml, "lxml")
results = soup.find_all("v:imagedata")

最新更新