lxml事件解析大文件只提取一些数据

时间:2013-04-14 18:19:09

标签: python xml-parsing lxml

我在这里看到了很多关于lxml解析的问题,虽然它们都非常有用,但是有些问题特定于被解析文件的结构。

在我的情况下,我有一个xml,如下所示:

<documents>
    <document>
        <id>123456</id>
        <element name="name">
            <value><![CDATA[john doe]]></value>
        </element>
        <element name="address">
            <value><![CDATA[no name street]]></value>
        </element>
    </document>
</documents>

实际的xml有更多的元素,但这仅仅是为了举例说明。 我的最终目的是将一些信息提取到csv中,以便得到以下结果:

id, name, address
123456,john doe,no name street

但是我的问题是解析文件以根据条件获取“value”元素中的值(如果父“element”具有特定属性)。

因为我要解析的真实文件大约是8gb,我认为最好使用lxml的iterparse来避免在内存中存储一​​棵大树。

这是我现在的代码,如果“element”的属性“name”等于列表“属性”中指定的值,那么在尝试检查下一个元素的文本时,我会陷入困境“:

from lxml import etree

attributes = ("name", "address")
context = etree.iterparse("test.xml", tag="document")

for event, element in context:
    for child in element:
        if child.attrib.get("name") in attributes:
            print child.getnext().text

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

它不是真正的“下一个”,而是后代,所以你可以再做一个循环,我想。如果value始终是唯一的子元素,则可以执行以下操作:

from lxml import etree

attributes = ("name", "address")
context = etree.iterparse("test.xml", tag="document")

for event, element in context:
    for child in element:
        if child.attrib.get("name") in attributes:
            print next(c for c in child).text
    element.clear() # clear the subtree from the memory

否则你可以在if里面做一个完整的for循环,有点像

if child.attrib.get("name") in attributes:
    for subchild in child:
        if subchild.tag == 'value':
            print subchild.text