在Python中读取Maven Pom xml

2024-04-27 19:02:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个pom文件,定义如下:

<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>org.welsh</groupId>
<artifactId>my-site</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<profiles>
    <profile>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.welsh.utils</groupId>
                    <artifactId>site-tool</artifactId>
                    <version>1.0</version>
                    <executions>
                        <execution>
                            <configuration>
                                <mappings>
                                    <property>
                                        <name>homepage</name>
                                        <value>/content/homepage</value>
                                    </property>
                                    <property>
                                        <name>assets</name>
                                        <value>/content/assets</value>
                                    </property>
                                </mappings>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
</project>

我想在name&;value元素下的property元素下构建一个字典。

因此,我试图找出如何获取所有可能的mappings元素(如果是多个构建配置文件),以便能够获取其下的所有property元素,并且通过阅读有关Supported XPath syntax的信息,以下内容应打印出所有可能的文本/值元素:

import xml.etree.ElementTree as xml

pomFile = xml.parse('pom.xml')
root = pomFile.getroot()

for mapping in root.findall('*/mappings'):
    for prop in mapping.findall('.//property'):
        logging.info(prop.find('name').text + " => " + prop.find('value').text)

什么也没回。我试着打印出所有的mappings元素,得到:

>>> print root.findall('*/mappings')
[]

当我打印出root中的所有内容时,我得到:

>>> print root.findall('*')
[<Element '{http://maven.apache.org/POM/4.0.0}modelVersion' at 0x10b38bd50>, <Element '{http://maven.apache.org/POM/4.0.0}groupId' at 0x10b38bd90>, <Element '{http://maven.apache.org/POM/4.0.0}artifactId' at 0x10b38bf10>, <Element '{http://maven.apache.org/POM/4.0.0}version' at 0x10b3900d0>, <Element '{http://maven.apache.org/POM/4.0.0}packaging' at 0x10b390110>, <Element '{http://maven.apache.org/POM/4.0.0}name' at 0x10b390150>, <Element '{http://maven.apache.org/POM/4.0.0}properties' at 0x10b390190>, <Element '{http://maven.apache.org/POM/4.0.0}build' at 0x10b390310>, <Element '{http://maven.apache.org/POM/4.0.0}profiles' at 0x10b390390>]

这让我试着打印:

>>> print root.findall('*/{http://maven.apache.org/POM/4.0.0}mappings')
[]

但那也不管用。

任何建议都很好。

谢谢


Tags: nameorghttp元素valueapachepropertyroot
2条回答

我用python修改了pom.xml。似乎etree没有很好的记录。所有的东西都用了一段时间才开始工作,但现在似乎已经奏效了。


正如您在下面的代码片段中看到的,Maven使用名称空间http://maven.apache.org/POM/4.0.0。根节点中的属性xmlns定义默认命名空间。属性xmlns:xsi也定义了一个名称空间,但它只用于xsi:schemaLocation

<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">

要在像find这样的方法中使用像profile这样的标记,还必须指定名称空间。例如,您可以编写以下代码来查找所有profile标记。

import xml.etree as xml

pom = xml.parse('pom.xml')
for profile in pom.findall('//{http://maven.apache.org/POM/4.0.0}profile'):
    print(repr(profile))

另一个重要的事情是这里。使用xml文件aboive,*/对于本例将有相同的结果。但它不会对其他标签起作用,比如mappings。由于*仅代表一个级别,因此*/child可以扩展到parent/tagxyz/tag,但不能扩展到xyz/parent/tag


我认为这是上面代码中的主要问题。必须使用//代替*/来允许任何子元素,而不是只允许直接子元素。必须指定名称空间。使用此选项,您应该可以执行类似的操作来查找所有映射:

pom = xml.parse('pom.xml')
map = {}
for mapping in pom.findall('//{http://maven.apache.org/POM/4.0.0}mappings'
                           '/{http://maven.apache.org/POM/4.0.0}property'):
    name  = mapping.find('{http://maven.apache.org/POM/4.0.0}name').text
    value = mapping.find('{http://maven.apache.org/POM/4.0.0}value').text
    map[name] = value

但是像上面这样指定名称空间不是很好。您可以定义命名空间映射并将其作为findfindall的第二个参数:

# ...
nsmap = {'m': 'http://maven.apache.org/POM/4.0.0'}
for mapping in pom.findall('//m:mappings/m:property', nsmap):
    name  = mapping.find('m:name', nsmap).text
    value = mapping.find('m:value', nsmap).text
    map[name] = value

好的,当我从project元素中删除maven的内容时,我可以这样做:

for mapping in root.findall('*//mappings'):
    logging.info(mapping)
    for prop in mapping.findall('./property'):
        logging.info(prop.find('name').text + " => " + prop.find('value').text)

这将导致:

INFO:root:<Element 'mappings' at 0x10d72d350>
INFO:root:homepage => /content/homepage
INFO:root:assets => /content/assets

但是,如果我把Maven的东西放在上面,我可以做到:

for mapping in root.findall('*//{http://maven.apache.org/POM/4.0.0}mappings'):
    logging.info(mapping)
    for prop in mapping.findall('./{http://maven.apache.org/POM/4.0.0}property'):
        logging.info(prop.find('{http://maven.apache.org/POM/4.0.0}name').text + " => " + prop.find('{http://maven.apache.org/POM/4.0.0}value').text)

结果是:

INFO:root:<Element '{http://maven.apache.org/POM/4.0.0}mappings' at 0x10aa7f310>
INFO:root:homepage => /content/homepage
INFO:root:assets => /content/assets

不过,我很想知道如何避免考虑maven的东西,因为它把我锁定在这个格式。

编辑:

好吧,我想说得更详细一点:

import xml.etree.ElementTree as xml

def getMappingsNode(node, nodeName):
    if node.findall('*'):
        for n in node.findall('*'):
            if nodeName in n.tag:
                return n
        else:
            return getMappingsNode(n, nodeName)

def getMappings(rootNode):
    mappingsNode = getMappingsNode(rootNode, 'mappings')
    mapping = {}

    for prop in mappingsNode.findall('*'):
        key = ''
        val = ''

        for child in prop.findall('*'):
            if 'name' in child.tag:
                key = child.text

            if 'value' in child.tag:
                val = child.text

        if val and key:
            mapping[key] = val

    return mapping

pomFile = xml.parse('pom.xml')
root = pomFile.getroot()

mappings = getMappings(root)
print mappings

相关问题 更多 >