查找 lxml 的名称空间 URI

Finding namespace URIs for lxml

我正在使用 lxml 通过以下代码解析 XML 产品 Feed:

namespace = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}
data = [loc.text for loc in tree.xpath("//sm:urlset/sm:url/sm:loc",namespaces=namespace)]

这适用于我用作输入的大多数提要,但我偶尔会发现带有其他命名空间的提要,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
      xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
      xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="https://www.sitemaps.org/schemas/sitemap/0.9
            https://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">

<url>
  <loc>https://www.example.com/</loc>
  <priority>1.00</priority>
</url>

根据我的阅读,我需要在此处将额外的命名空间(我猜是 xmlns:xsi)添加到命名空间字典中,以使我的 xpath 与多个命名空间一起使用。 但是,这对我来说不是一个长期的解决方案,因为我将来可能会遇到其他不同的名称空间 - 我有没有办法 search/detect 甚至删除名称空间?元素树总是一样的,所以我的 xpath 不会改变。

谢谢

您不需要映射 xsi 前缀;这仅适用于 xsi:schemaLocation 属性。

您当前的映射与输入文件的区别在于 XML.

的默认命名空间中的“https”中有一个“s”

要处理两个名称空间 URI(或者实际上 urlset 可能具有的任何其他名称空间 URI)是首先获取根元素的名称空间 URI,然后在您的字典映射中使用它...

from lxml import etree

tree = etree.parse("input.xml")

root_ns_uri = tree.xpath("namespace-uri()")

namespace = {"sm": root_ns_uri}
data = [loc.text for loc in tree.xpath("//sm:urlset/sm:url/sm:loc", namespaces=namespace)]

print(data)

打印...

['https://www.example.com/']

如果 urlset 并不总是根元素,您可能想做这样的事情...

root_ns_uri = tree.xpath("namespace-uri(//*[local-name()='urlset'])")