【问题标题】:Most efficient method to extract data from this XML file从此 XML 文件中提取数据的最有效方法
【发布时间】:2012-06-23 01:12:29
【问题描述】:

XML 文件示例

<GateDocument> 
  <GateDocumentFeatures>
    ...
  </GateDocumentFeatures>
  <TextWithNodes>
    <Node id="0"/>
    MESSAGE SET
    <Node id="19"/> 
    <Node id="20"/>
    1. 1/1/09 - sample text 1
    <Node id="212"/>
    sample text 2
    <Node id="223"/>
    sample text 3
    ...
    <Node id="160652"/>
  </TextWithNodes>
  <AnnotationSet></AnnotationSet>
  <AnnotationSet Name="SomeName">
    ...
  </AnnotationSet>
</GateDocument>

刚开始,这是我第一次使用 Python 编码并处理 XML,如果我错过了非常明显的事情,非常抱歉!

我的目标是提取特定节点 ID 处的示例文本。

第一次尝试 - 我使用了 minidom,它没有为我提供处理提取的正确方法 (http://stackoverflow.com/questions/11122736/extracting-text-from-xml-node-with-minidom)由于自闭合标签中节点 ID 的这种奇怪格式。

第二次尝试 - 我在查看 lxml 时接受了建议,我已成功将文本提取为如下内容:

['\n\t\t','n\t\tMESSAGE SET\n\t\t','\n\t\t','\n\t\t1. 1/1/09 - sample text 1,....,'\n\t']

通过一些清理,我想我可以得到很好的文本,但是,我丢失了关联的节点 id 值。

附上代码:

from lxml import etree
from StringIO import StringIO
xmlfile = ('C:\...AnnotationsXML.xml')
xmldoc = etree.parse(xmlfile)  
print xmldoc.xpath("//TextWithNodes/text()")

所以我想我的问题是:

  1. 有没有办法在没有 \n\t\t 的情况下提取上述内容?我读到它是空间格式(即制表符),但我不确定&lt;Node id = 0&gt; 去了哪里。
  2. 是否有更好或更有效的方法来提取此文件?

谢谢!

【问题讨论】:

  • 要么在路径中使用正斜杠,要么在 Windows 上使用原始字符串 (r'...'),否则你会发现某些路径中突然出现换行符和制表符。
  • Node 元素与散布在这些元素中的文本之间有什么联系?这种 XML 格式看起来很糟糕。
  • @FrancisAvila 我相信文本分析软件 (GATE) 允许对文本进行注释。因此,我可以挑选出一个单词/短语并用一个特征对其进行注释。如果整个文档是一个字符串,我相信节点 id 是整个文档的起始索引。 (如果我描述正确的话)
  • 那个描述不是特别有启发性。这里的问题是,您似乎在表达节点和文本字符串之间的某种“包含”关系,但 XML 并没有表达任何这种关系。所以要么这种 XML 格式设计得很糟糕,要么你误解了 XML 所表达的底层数据模型。

标签: python xml parsing lxml elementtree


【解决方案1】:
In [1]: from lxml import etree

In [2]: tree = etree.parse('awful.xml')

In [3]: data = {int(node.attrib['id']): node.tail.strip()
   ...: for node in tree.xpath('//TextWithNodes/Node') if node.tail.strip()}

In [4]: data
Out[4]: 
{0: 'MESSAGE SET',
 20: '1. 1/1/09 - sample text 1',
 212: 'sample text 2',
 223: 'sample text 3'}

strip 用于删除 \t\n 之类的内容,tail 将文本放在标签后面。

【讨论】:

  • +1 用于优雅地使用字典理解。对node.tail.strip() 的重复调用是不幸的,但除非/直到 Python 支持 en passant 赋值(ha! as if!),这是不可避免的。
  • 太棒了。盯着它,然后把它一块一块地拆开,直到我详细掌握了这个解决方案的每一个元素。快速提问 - 我的消息出来但不是按节点 ID 的顺序排列(但是,它都存在),我只是好奇 In[3] 它不是从开始索引 0 开始按顺序解析吗? {0:'TEXT',40960:'TEXT2',106499:'TEXT3',90113:'TEXT4'}
  • @Jasmine 我认为它是按顺序解析的,问题是数据然后保存到字典中(当然,您可以更改它),而字典没有顺序。你说你需要将文本与 id 相关联,所以我使用了 dict。您可以选择更适合您的选项,但 dict 是一种相当灵活的结构。如果您需要按顺序存储它(当然),请改用列表。
  • @LevLevitsky 啊,我明白了,仅来自 java 经验,我不知道这些变量是什么结构。不过,我可以与 dic 合作,谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-12-24
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多