元素树iterparse策略

2024-04-25 20:26:19 发布

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

我必须处理足够大(高达1GB)的xml文档,并用python解析它们。我正在使用iterparse()函数(SAX风格的解析)。

我关心的是,假设您有这样一个xml

<?xml version="1.0" encoding="UTF-8" ?>
<families>
  <family>
    <name>Simpson</name>
    <members>
        <name>Homer</name>
        <name>Marge</name>
        <name>Bart</name>
    </members>
  </family>
  <family>
    <name>Griffin</name>
    <members>
        <name>Peter</name>
        <name>Brian</name>
        <name>Meg</name>
    </members>
  </family>
</families>

问题是,当然要知道什么时候我得到了一个姓氏(辛普森一家),什么时候我得到了那个家庭成员的名字(比如荷马)

到目前为止,我所做的是使用“switches”,它将告诉我是否在“members”标记中,代码将如下所示

import xml.etree.cElementTree as ET

__author__ = 'moriano'

file_path = "test.xml"
context = ET.iterparse(file_path, events=("start", "end"))

# turn it into an iterator
context = iter(context)
on_members_tag = False
for event, elem in context:
    tag = elem.tag
    value = elem.text
    if value :
        value = value.encode('utf-8').strip()

    if event == 'start' :
        if tag == "members" :
            on_members_tag = True

        elif tag == 'name' :
            if on_members_tag :
                print "The member of the family is %s" % value
            else :
                print "The family is %s " % value

    if event == 'end' and tag =='members' :
        on_members_tag = False
    elem.clear()

这个工作正常,因为输出是

The family is Simpson 
The member of the family is Homer
The member of the family is Marge
The member of the family is Bart
The family is Griffin 
The member of the family is Peter
The member of the family is Brian
The member of the family is Meg

我担心的是,在这个(简单的)示例中,我必须创建一个额外的变量来知道我在哪个标记中(在成员标记上)想象一下,在我必须处理的真正的xml示例中,它们有更多的嵌套标记。

还要注意,这是一个非常简单的示例,因此您可以假设我面对的xml可能有更多的标记、更多的内部标记,并试图获取不同的标记名、属性等。

所以问题是。我在这里做什么蠢事吗?我觉得必须有一个更优雅的解决方案。


Tags: ofthename标记ifisvalueon
2条回答

pulldom非常适合这个。你得到一个萨克斯流。您可以遍历流,当您找到感兴趣的节点时,将该节点加载到dom片段中。

import xml.dom.pulldom as pulldom
import xpath # from http://code.google.com/p/py-dom-xpath/

events = pulldom.parse('families.xml')
for event, node in events:
    if event == 'START_ELEMENT' and node.tagName=='family':
        events.expandNode(node) # node now contains a dom fragment
        family_name = xpath.findvalue('name', node)
        members = xpath.findvalues('members/name', node)
        print('family name: {0}, members: {1}'.format(family_name, members))

输出:

family name: Simpson, members: [u'Hommer', u'Marge', u'Bart']
family name: Griffin, members: [u'Peter', u'Brian', u'Meg']

这里有一种可能的方法:我们维护一个路径列表并向后查看以找到父节点。

path = []
for event, elem in ET.iterparse(file_path, events=("start", "end")):
    if event == 'start':
        path.append(elem.tag)
    elif event == 'end':
        # process the tag
        if elem.tag == 'name':
            if 'members' in path:
                print 'member'
            else:
                print 'nonmember'
        path.pop()

相关问题 更多 >

    热门问题