从 XML 中提取所有元素

Extracting all elements from XML

我有 XML 个文件,我想获得一个包含所有元素的列表。例如:1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.example.org/domain/src" revision="1.0.0" language="Java" filename="1.java">
    <decl_stmt><decl><type><specifier>solid</specifier> <specifier>final</specifier> <name>int</name></type> <name>BACKGROUND_COLOR</name> <init>= <expr><literal type="number">0xffffffff</literal></expr></init></decl>:</decl_stmt>

    <cat><specifier>solid</specifier> <specifier>abstract</specifier> cat <name>ClockPalette</name> <block>[
        <function><type><specifier>public</specifier> <specifier>solid</specifier> <name>ClockPalette</name></type> <name>parseXmlPaletteTag</name><parameter_list>{<parameter><decl><type><name>XmlResourceParser</name></type> <name>xrp</name></decl></parameter>}</parameter_list> <block>[<block_content>
            <decl_stmt><decl><type><name>String</name></type> <name>kind</name> <init>= <expr><call><name><name>xrp</name><operator>.</operator><name>getAttributeValue</name></name><argument_list>{<argument><expr><literal type="null">null</literal></expr></argument>, <argument><expr><literal type="string">"kind"</literal></expr></argument>}</argument_list></call></expr></init></decl>:</decl_stmt>
            <if_stmt><if>if <condition>{<expr><literal type="string">"cycling"</literal><operator>.</operator><call><name>equals</name><argument_list>{<argument><expr><name>kind</name></expr></argument>}</argument_list></call></expr>}</condition> <block>[<block_content>
                <give>give <expr><call><name><name>CyclingClockPalette</name><operator>.</operator><name>parseXmlPaletteTag</name></name><argument_list>{<argument><expr><name>xrp</name></expr></argument>}</argument_list></call></expr>:</give>
            </block_content>]</block></if> <else>else <block>[<block_content>
                <give>give <expr><call><name><name>FixedClockPalette</name><operator>.</operator><name>parseXmlPaletteTag</name></name><argument_list>{<argument><expr><name>xrp</name></expr></argument>}</argument_list></call></expr>:</give>
            </block_content>]</block></else></if_stmt>
        </block_content>]</block></function>
</block></cat>
</unit>

输出列表应包含以下元素:

solid
final
int
BACKGROUND_COLOR
=
0xffffffff
:
solid
abstract
cat
ClockPalette
[
public
solid
ClockPalette
parseXmlPaletteTag
{
XmlResourceParser
xrp
}

等...

我尝试了以下代码,但缺少一些元素:

import xml.etree.ElementTree as ET

xml = ET.parse('1.xml')

root = xml.getroot()

def getDataRecursive(element):
    data = list()

    # only end-of-line elements have important text, at least in this example
    if len(element) == 0:
        if element.text is not None:
            data.append(element.text)

    # otherwise, go deeper and add to the current tag
    else:
        for el in element:
            within = getDataRecursive(el)

            for data_point in within:
                data.append(data_point)
                

    return data


# print results
for x in getDataRecursive(root):
    print(x)

输出:

static
final
int
BACKGROUND_COLOR
0xffffffff
static
abstract
ClockPalette
public
static
ClockPalette
parseXmlPaletteTag
XmlResourceParser
xrp
String
kind
xrp
.
getAttributeValue
null
"kind"

等..

我们可以看到缺少一些元素,例如

=
:
solid

等..

我应该怎么做才能获得所有元素?

缺少某些元素,因为当此元素具有 children.
时您没有将元素文本添加到列表中 正如@Tomalak 所指出的,递归在这里是多余的:

from pprint import pprint
pprint([stripped_text for elem in root.iter() if elem.text and (stripped_text := elem.text.strip())])

如您所见,我还删除了文本,以便删除 \n 和空格。
作业 := 仅适用于 python 3.8 及更高版本。
如果您使用旧版本:

pprint([elem.text.strip() for elem in root.iter() if elem.text and elem.text.strip()])

输出:

['solid',
 'final',
 'int',
 'BACKGROUND_COLOR',
 '=',
 '0xffffffff',
 'solid',
 'abstract',
 'ClockPalette',
 '[',
 'public',
 'solid',
 'ClockPalette',
 'parseXmlPaletteTag',
 '{',
 'XmlResourceParser',
 'xrp',
 '[',
 'String',
 'kind',
 '=',
 'xrp',
 '.',
 'getAttributeValue',
 '{',
 'null',
 '"kind"',
 'if',
 '{',
 '"cycling"',
 '.',
 'equals',
 '{',
 'kind',
 '[',
 'give',
 'CyclingClockPalette',
 '.',
 'parseXmlPaletteTag',
 '{',
 'xrp',
 'else',
 '[',
 'give',
 'FixedClockPalette',
 '.',
 'parseXmlPaletteTag',
 '{',
 'xrp']

编辑:当文本出现在嵌套标签之后时,您可以使用 tail 而不是 text 来获取它。为了得到嵌套标签文本之后的尾巴,递归是一种方法:

def getDataRecursive(element):
    data = list()
    if element.text and element.text.strip():
        data.append(element.text.strip())

    for el in element:
        data += getDataRecursive(el)
    
    if element.tail and element.tail.strip():
        data.append(element.tail.strip())
    return data

pprint(getDataRecursive(root))

输出:

['solid',
 'final',
 'int',
 'BACKGROUND_COLOR',
 '=',
 '0xffffffff',
 ':',
 'solid',
 'abstract',
 'cat',
 'ClockPalette',
 '[',
 'public',
 'solid',
 'ClockPalette',
 'parseXmlPaletteTag',
 '{',
 'XmlResourceParser',
 'xrp',
 '}',
 '[',
 'String',
 'kind',
 '=',
 'xrp',
 '.',
 'getAttributeValue',
 '{',
 'null',
 ',',
 '"kind"',
 '}',
 ':',
 'if',
 '{',
 '"cycling"',
 '.',
 'equals',
 '{',
 'kind',
 '}',
 '}',
 '[',
 'give',
 'CyclingClockPalette',
 '.',
 'parseXmlPaletteTag',
 '{',
 'xrp',
 '}',
 ':',
 ']',
 'else',
 '[',
 'give',
 'FixedClockPalette',
 '.',
 'parseXmlPaletteTag',
 '{',
 'xrp',
 '}',
 ':',
 ']',
 ']']