1

我正在尝试使用 python 解析 maven 项目定义以提取版本。

项目定义如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>...</groupId>
   <artifactId>...</artifactId>
   <version>1.6.0-SNAPSHOT</version>
   ...
</project>

我可以使用以下方法提取版本:

root = ET.fromstring(xml)
version = root.find('./p:version', { 'p': 'http://maven.apache.org/POM/4.0.0' })
print(version.text)

prints: 1.6.0-SNAPSHOT

但是,使用的命名空间可能会改变,我不想依赖于此。有没有办法提取命名空间以在我后续的 xpath 表达式中使用?

我尝试了以下方法,以查看 xmlns 本身是否暴露,但没有运气:

root = ET.fromstring(xml)
for k in root.attrib:
    print('%s => %s' % (k, root.attrib[k]))

prints: {http://www.w3.org/2001/XMLSchema-instance}schemaLocation => http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd
4

2 回答 2

2

但是,使用的命名空间可能会改变,我不想依赖于此。

您是说名称空间 uri 可能会更改,还是前缀可能会更改?如果只是前缀,那么这不是问题,因为重要的是 XPath 中的前缀与您提供给 XPath 评估程序的前缀匹配。在任何一种情况下,自动检测命名空间都可能是一个错误的调用。假设有人决定像这样开始生成 XML:

<proj:project xmlns:proj="http://maven.apache.org/POM/4.0.0" 
xmlns:other="http://maven.apache.org/POM/5.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/maven-v4_0_0.xsd">

它仍然完美地代表了与您的示例相同的命名空间中的 XML,但您不知道proj前缀是您正在寻找的命名空间前缀。

我认为 Apache 不太可能突然更改其官方 XML 格式之一的名称空间,但如果您真的担心它,应该始终可以选择使用 local-name() 来与名称空间无关地找到您的节点重新寻找:

version = root.find('./*[local-name() = "version"]')

另外,我不熟悉 elementTree 库,但您可以尝试此操作以尝试获取有关 XML 文档名称空间的信息,看看是否可以:

namespaces = root.findall('//namespace::*')
于 2013-01-16T17:54:59.893 回答
2

不幸的是,ElementTree命名空间支持相当不完整。

您需要使用xml.etree.ElementTree模块中的内部方法来获取命名空间映射:

_, namespaces = ET._namespaces(root, 'utf8')

namespaces现在是一个以 URI 作为键,前缀作为值的字典。

你可以改用lxml。该库实现了相同的 ElementTree API,但大大增强了该 API。

例如,每个节点都包含一个.nsmap将前缀映射到 URI 的属性,包括 key 下的默认命名空间None

于 2013-01-16T16:37:45.163 回答