首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:使用mini dom通过XML进行解析

Python:使用mini dom通过XML进行解析
EN

Stack Overflow用户
提问于 2013-03-29 18:45:50
回答 2查看 1.5K关注 0票数 0

我正在解析一个相当大小的xml文件,遇到了一个问题。由于某些原因,我无法提取数据,即使我以前对不同的xml文件做过完全相同的事情。

下面是我的代码片段:(程序的其余部分,我已经测试过了,它们运行得很好)编辑:更改为包含一个测试尝试&除了块

代码语言:javascript
复制
def parseXML():
    file = open(str(options.drugxml),'r')
    data = file.read()
    file.close()
    dom = parseString(data)
    druglist = dom.getElementsByTagName('drug')

    with codecs.open(str(options.csvdata),'w','utf-8') as csvout, open('DrugTargetRel.csv','w') as dtout:
        for entry in druglist:
        count = count + 1
        try:
            drugtype = entry.attributes['type'].value
            print count
        except:
            print count
            print entry
            drugidObj = entry.getElementsByTagName('drugbank-id')[0]
            drugid = drugidObj.childNodes[0].nodeValue
            drugnameObj = entry.getElementsByTagName('name')[0]
            drugname = drugnameObj.childNodes[0].nodeValue

            targetlist = entry.getElementsByTagName('target')
            for target in targetlist:
                targetid = target.attributes['partner'].value
                dtout.write((','.join((drugid,targetid)))+'\n')

            csvout.write((','.join((drugid,drugname,drugtype)))+'\n')

如果您想知道XML文件的模式大致是什么样子,下面是一个糟糕透顶的级别草图:

代码语言:javascript
复制
<drugs>
   <drug type='something' ...>
      <drugbank-id>
      <name>
      ...
      <targets>
         <target partner='something'>

我在这里输入的那些文件,我需要从XML文件中提取出来,并把它放在csv文件中(如上面的代码所示),而且代码以前也适用于不同的xml文件,不知道为什么它不能处理这个文件。我在“类型”上得到了KeyError,我还在网上发现了索引错误,即使每种药物都有一种药物,但都可以提取药物。我在搞什么鬼?

编辑:我正在提取的东西保证在每种药物中。

对于任何关心此事的人,下面是我正在解析的XML文件的链接:http://www.drugbank.ca/system/downloads/current/drugbank.xml.zip

编辑:在实现了一个try &除块(见上面)之后,我发现了以下内容:在模式中,有一些称为“药物交互”的部分,其中也有一个子字段名为see。就像这样:

代码语言:javascript
复制
 <drugs>
       <drug type='something' ...>
          <drugbank-id>
          <name>
          ...
          <targets>
             <target partner='something'>
          <drug-interactions>
             <drug>

我想我的药物列表=dom.getElementsByTagName(‘药物’)也是无意中捡到的--我不知道我怎么能解决这个问题.有什么建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-29 20:19:56

基本上,当parsin使用xml时,您不能依赖您知道结构这一事实。找出代码中的结构是一个很好的实践。

因此,每次访问元素或属性时,请先检查是否存在。在您的代码中,它意味着:

确保药物元素上有一个属性“type”:

代码语言:javascript
复制
drugtype = entry.attributes['type'].value if entry.attributes.has_key('type') else 'defaulttype'

确保getElementsByTagName在访问其元素之前不返回空数组:

代码语言:javascript
复制
drugbank-id = entry.getElementsByTagName('drugbank-id')
drugidObj = drugbank-id[0] if drugbank-id else None

另外,在访问子节点之前,请确保有以下内容:

代码语言:javascript
复制
if drugidObj.hasChildNodes:
    drugid = drugidObj.childNodes[0].nodeValue

或者使用for循环循环遍历它们。

当您在药物组上调用getElementsByTagName时,它会返回所有元素,包括嵌套元素。若要只获取药物元素(这些元素是药物元素的dirrect子元素),您必须使用childNodes属性。

票数 1
EN

Stack Overflow用户

发布于 2013-03-29 19:44:39

我有一种感觉,也许是因为内存不足或其他原因发生了一些奇怪的事情,所以我用迭代器重写了解析器,并对每种药物进行了测试,并使程序得以完成,而不引起异常。

基本上,我在这里要做的是,不是将整个XML文件加载到内存中,而是解析每个<drug></drug>标记的开头和结尾的XML文件。然后每次使用minidom解析。

代码可能有点脆弱,因为我假设每个<drug></drug>对都在各自的行上。希望这比伤害更有帮助。

代码语言:javascript
复制
#!python
import codecs
from xml.dom import minidom

class DrugBank(object):
    def __init__(self, filename):
        self.fp = open(filename, 'r')

    def __iter__(self):
        return self

    def next(self):
        state = 0

        while True:
            line = self.fp.readline()

            if state == 0:
                if line.strip().startswith('<drug '):
                    lines = [line]
                    state = 1
                    continue

                if line.strip() == '</drugs>':
                    self.fp.close()
                    raise StopIteration()

            if state == 1:
                lines.append(line)
                if line.strip() == '</drug>':
                    return minidom.parseString("".join(lines))

with codecs.open('csvout.csv', 'w', 'utf-8') as csvout, open('dtout.csv', 'w') as dtout:
    db = DrugBank('drugbank.xml')
    for dom in db:
        entry = dom.firstChild
        drugtype = entry.attributes['type'].value
        drugidObj = entry.getElementsByTagName('drugbank-id')[0]
        drugid = drugidObj.childNodes[0].nodeValue
        drugnameObj = entry.getElementsByTagName('name')[0]
        drugname = drugnameObj.childNodes[0].nodeValue

        targetlist = entry.getElementsByTagName('target')
        for target in targetlist:
            targetid = target.attributes['partner'].value
            dtout.write((','.join((drugid,targetid)))+'\n')

        csvout.write((','.join((drugid,drugname,drugtype)))+'\n')

这里有一个有趣的读物,可能对你有进一步的帮助:http://www.ibm.com/developerworks/xml/library/x-hiperfparse/

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

https://stackoverflow.com/questions/15709499

复制
相关文章

相似问题

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