Простой обход dom в Python с использованием xml.etree.ElementTree

Например. рассмотрите возможность разбора файла pom.xml:

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

    <parent>
        <groupId>com.parent</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <modelVersion>2.0.0</modelVersion>
    <groupId>com.parent.somemodule</groupId>
    <artifactId>some_module</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Some Module</name>
    ...

Код:

import xml.etree.ElementTree as ET

tree = ET.parse(pom)
root = tree.getroot()

groupId = root.find("groupId")
artifactId = root.find("artifactId")

И groupId, и artifactId равны None. Почему, если они прямые потомки корня? Я попытался заменить root на tree (groupId = tree.find("groupId")), но это ничего не изменило.


person amphibient    schedule 15.01.2014    source источник
comment
возможный дубликат Синтаксический анализ XML с пространством имен в Python ElementTree   -  person Martijn Pieters    schedule 15.01.2014


Ответы (2)


Проблема в том, что у вас нет дочернего элемента с именем groupId, у вас есть дочерний элемент с именем {http://maven.apache.org/POM/4.0.0}groupId, потому что etree не игнорирует пространства имен XML, а использует "универсальные имена". См. раздел Работа с пространствами имен и полными именами в документации effbot.

person abarnert    schedule 15.01.2014
comment
Могу ли я как-то заставить его игнорировать пространство имен? - person amphibient; 15.01.2014
comment
@amphibient: Не напрямую, нет. Если вы прочитаете страницу документа, на которую я ссылаюсь, она покажет вам различные способы правильного решения этой проблемы. - person abarnert; 15.01.2014
comment
@amphibient: это не отсталость; XML, который использует пространства имен для решения проблем неоднозначности, будет нарушен, если вы их проигнорируете. (XML в целом отсталый, но это другая история...) Для быстрых и грязных скриптов вам нужен быстрый и грязный синтаксический анализатор, такой как BeautifulSoup, а не синтаксический анализатор, который пытается быть правильным. - person abarnert; 15.01.2014
comment
@amphibient: В любом случае, я мог бы дать вам код для решения вашей проблемы, но если вы на самом деле не понимаете пространства имен и универсальные имена, этот код не принесет вам никакой пользы, поэтому вам придется прочитать этот документ. Если потом будут вопросы, могу помочь. - person abarnert; 15.01.2014
comment
что я считаю отсталым, так это неспособность игнорировать пространство имен и использовать его, как если бы корень был просто <project>, а не <project xmlns="...">. почему бы не использовать функцию игнорирования для упрощения обработки? - person amphibient; 15.01.2014
comment
@amphibient: Потому что это было бы неправильно так же часто, как и полезно. Это все равно, что сказать, что Python отсталый из-за того, что не позволяет вам писать 'answer: ' + 42. Конечно, иногда это было бы полезно, но также было бы привлекательной неприятностью (как доказывают такие языки, как PHP и Tcl). - person abarnert; 15.01.2014

Просто чтобы расширить комментарий abarnert о BeautifulSoup, если вы ДЕЙСТВИТЕЛЬНО просто хотите быстрое и грязное решение проблемы, это, вероятно, самый быстрый способ сделать это. Я реализовал это (для личного сценария), который использует bs4, где вы можете перемещаться по дереву с помощью

element = dom.getElementsByTagNameNS('*','elementname')

Это будет ссылаться на dom, используя ЛЮБОЕ пространство имен, что удобно, если вы знаете, что у вас есть только одно в файле, чтобы не было двусмысленности.

person Sean K.    schedule 15.01.2014