首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lxml iterparse with objectify

lxml iterparse with objectify
EN

Stack Overflow用户
提问于 2018-04-17 22:17:23
回答 1查看 489关注 0票数 2

如何解析一个大的XML文件并将其元素作为ObjectifiedElement处理(使用objectify解析器)。

我没有找到比这更好的解决方案:

代码语言:javascript
复制
from lxml import etree, objectify
for event, elt in etree.iterparse('onebigfile.xml', tag='MyTag'):
    oelt = objectify.fromstring(etree.tostring(elt))
    my_process(oelt)

如何避免这种中间字符串表示?

EN

回答 1

Stack Overflow用户

发布于 2018-04-18 01:06:21

我认为使用iterparse构建一个定制的数据提取器非常容易,它完全不需要使用objectify。

对于这个示例,我使用了一个.NET参考XML文件,它看起来有点像这样:

代码语言:javascript
复制
<doc>
  <assembly>
    <name>System.IO</name>
  </assembly>
  <members>
    <member name="T:System.IO.BinaryReader">
      <summary>Reads primitive data types as binary values in a specific encoding.</summary>
      <filterpriority>2</filterpriority>
    </member>
    <member name="M:System.IO.BinaryReader.#ctor(System.IO.Stream)">
      <summary>Initializes a new instance of the <see cref="T:System.IO.BinaryReader" /> class based on the specified stream and using UTF-8 encoding.</summary>
      <param name="input">The input stream. </param>
      <exception cref="T:System.ArgumentException">The stream does not support reading, is null, or is already closed. </exception>
    </member>
    <member name="M:System.IO.BinaryReader.#ctor(System.IO.Stream,System.Text.Encoding)">
      <summary>Initializes a new instance of the <see cref="T:System.IO.BinaryReader" /> class based on the specified stream and character encoding.</summary>
      <param name="input">The input stream. </param>
      <param name="encoding">The character encoding to use. </param>
      <exception cref="T:System.ArgumentException">The stream does not support reading, is null, or is already closed. </exception>
      <exception cref="T:System.ArgumentNullException">
        <paramref name="encoding" /> is null. </exception>
    </member>
    <!-- ... many more members like this -->
  </members>
</doc>

假设您希望提取所有成员及其名称、摘要和属性作为字典列表,如下所示:

代码语言:javascript
复制
{
  'summary': 'Reads primitive data types as binary values in a specific encoding.', 
  'name': 'T:System.IO.BinaryReader'
}
{
  'summary': 'Initializes a new instance of the ', 
  '@input': 'The input stream. ', 
  'name': 'M:System.IO.BinaryReader.#ctor(System.IO.Stream)'
}
{
  'summary': 'Initializes a new instance of the class based on the specified stream and using UTF-8 encoding.', 
  '@input': 'The input stream. ',
  '@encoding': 'The character encoding to use. ',
  'name': 'M:System.IO.BinaryReader.#ctor(System.IO.Stream,System.Text.Encoding)'
}

你可以这样做:

  • lxml.iterparsestartend events一起使用
  • <member>元素启动时,准备一个新的dict (item)
  • when我们在<member>元素内,将我们感兴趣的任何内容添加到dict
  • <member>元素结束时,最终确定dict并生成它
  • 将D20设置为None用作“-flag

在代码中:

代码语言:javascript
复制
import lxml
from lxml import etree

def text_content(elt):
    return ' '.join([t.strip() for t in elt.itertext()])

def extract_data(xmlfile):
    item = None

    for event, elt in etree.iterparse(xmlfile, events=['start', 'end']):
        if elt.tag == 'member':
            if event == 'start':
                item = {}
            else:
                item['name'] = elt.attrib['name']
                yield item
                item = None

        if item == None:
            continue

        if event == 'end':
            if elt.tag in ('summary', 'returns'):
                item[elt.tag] = text_content(elt)
                continue

            if elt.tag == 'param':
                item['@' + elt.attrib['name']] = text_content(elt)
                continue


testfile = r'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.IO.xml'

for item in extract_data(testfile):
    print(item)

通过这种方式,您可以获得最快、最节省内存的解析,以及对所查看数据的精细控制。即使没有中间的tostring()/fromstring(),使用objectify也会更加浪费。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49880545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档