1

我有一个从 etree 元素返回列表的函数,但它不查看嵌套元素。

<elem>
    <variable id="getthis">
        <!-- / -->
    </variable>
    <if>
        <variable id="alsoGetThis">
            <!-- Keep looping through all elements -->
        </variable>
    </if>
</elem>

(我正在使用Valid XML

所以目前里面的变量<if>被忽略了,那么你怎么能循环遍历树的所有级别呢?我假设这是一个简单的任务,但也许我错了。(我是 Python 新手,并不总是像程序员一样思考)

Python func 获取变量:

def collect_vars(self, elem):
    elemVars = []
    if elem.tag == 'variable':
        elemVars.append(elem.attrib['id'])
    elif e in elem == 'variable': # don't want to be doing these
        elemVars.append(e.attrib['id'])
    return elemVars

所以我想要结束的是elemVars包含给定中所有变量ID的列表<elem>

4

2 回答 2

4

考虑学习XPath并使用xpathLXML 的成员。假设您的 XML 树被调用t,就好像您已发出

>>> s = """<elem>
    <variable id="getthis">
        <!-- / -->
    </variable>
    <if>
        <variable id="alsoGetThis">
            <!-- Keep looping through all elements -->
        </variable>
    </if>
</elem>
"""
>>> t = etree.fromstring(s)

然后你可以找到树中的所有元素

>>> t.xpath("//*")
[<Element elem at 0x2809b40>, <Element variable at 0x2809be0>, <Element if at 0x2809af0>, <Element variable at 0x2809c80>]

和所有variable元素

>>> t.xpath("//variable")
[<Element variable at 0x2809be0>, <Element variable at 0x2809c80>]

xpath返回满足您指定的 XPath 条件的元素列表,表示为元素树:

>>> [x.attrib["id"] for x in t.xpath("//variable")]
['getthis', 'alsoGetThis']
于 2012-05-17T14:05:26.527 回答
1

您面临的问题是您没有访问文件中的所有节点。您只是在访问元素的子elem元素,而不是访问这些元素的子元素。为了说明这一点,运行以下命令(我已将您的 XML 编辑为有效):

from xml.etree.ElementTree as etree

xml_string = """<elem>
    <variable id="getthis" />
    <if>
        <variable id="alsoGetThis" />
    </if>
    </elem>"""

e = etree.fromstring(xml_string)

for node in e:
    print node

结果是

<Element variable at 7f53fbdf1cb0>
<Element if at 7f53fbdf1cf8>

所以你没有访问variable节点的孩子if。您将需要递归访问 XML 文件中的每个节点,即您的函数collect_vars需要调用自身。我将稍后发布一些代码来说明这一点。

编辑:正如所承诺的,一些代码可以从元素树中获取所有id属性。我没有像 Niek de Klein 那样使用蓄电池,而是使用了发电机。这有许多优点。例如,这一次返回一个ids,因此您可以在任何时候停止处理,例如,如果遇到某个id问题,这样可以节省读取整个 XML 文件的时间。

def get_attrs(element, tag, attr):
    """Return attribute `attr` of `tag` child elements of `element`."""

    # If an element has any cildren (nested elements) loop through them:
    if len(element):
         for node in element:
            # Recursively call this function, yielding each result:
            for attribute in get_attrs(node, tag, attr):
                yield attribute

    # Otherwise, check if element is of type `tag` with attribute `attr`, if so
    # yield the value of that attribute.
    if element.tag == 'variable':
        if attr in element.attrib:
            yield element.attrib[attr]

ids = [id for id in get_attrs(e, 'variable', 'id')]

print ids

产生了结果

 ['getthis', 'alsoGetThis']
于 2012-05-17T13:30:42.323 回答