0

適切なサイズの xml ファイルを解析していて、問題が発生しました。以前に別のxmlファイルでまったく同じことを行ったにもかかわらず、何らかの理由でデータを抽出できません。

これが私のコードのスニペットです:(プログラムの残りの部分、私はテストしましたが、正常に動作します)編集:テスト用のtry&exceptブロックを含めるように変更されました

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 ファイルのスキーマが大まかにどのようになっているのか知りたい方のために、レベルの大まかなスケッチを以下に示します。

<drugs>
   <drug type='something' ...>
      <drugbank-id>
      <name>
      ...
      <targets>
         <target partner='something'>

ここに入力したものは、XML ファイルから抽出して csv ファイルに貼り付ける必要があり (上記のコードが示すように)、コードは以前に別の xml ファイルで機能していましたが、なぜこのファイルで機能しないのかわかりません。「タイプ」で KeyError が発生しました。また、すべてのドラッグにドラッグ ID があるにもかかわらず、ドラッグ ID を抽出する行でインデックス作成エラーが発生しました。私はここで何を台無しにしていますか?

編集:私が抽出しているものは、各薬物に含まれていることが保証されています.

気になる人のために、私が解析している XML ファイルへのリンクを次に示します: http://www.drugbank.ca/system/downloads/current/drugbank.xml.zip

編集: try & except ブロック (上記を参照) を実装した後、私が見つけたものは次とおりです。このように:

 <drugs>
       <drug type='something' ...>
          <drugbank-id>
          <name>
          ...
          <targets>
             <target partner='something'>
          <drug-interactions>
             <drug>

私の行 druglist = dom.getElementsByTagName('drug') も意図せずにそれらを拾っていると思います-これを修正する方法がわかりません...何か提案はありますか?

4

2 に答える 2

1

基本的に、xml を解析するときは、構造を知っているという事実に頼ることはできません。コード内の構造を見つけることは良い習慣です。

したがって、要素または属性にアクセスするたびに、存在するかどうかを事前に確認してください。あなたのコードでは、次のことを意味します。

ドラッグ要素に「タイプ」属性があることを確認してください:

drugtype = entry.attributes['type'].value if entry.attributes.has_key('type') else 'defaulttype'

要素にアクセスする前に、getElementsByTagName が空の配列を返さないことを確認してください。

drugbank-id = entry.getElementsByTagName('drugbank-id')
drugidObj = drugbank-id[0] if drugbank-id else None

また、子ノードにアクセスする前に、次のものがあることを確認してください。

if drugidObj.hasChildNodes:
    drugid = drugidObj.childNodes[0].nodeValue

または、 for loop を使用してそれらをループします。

また、 Drugs 要素を呼び出すとgetElementsByTagName、ネストされた要素を含むすべての要素が返されます。Drugs 要素の直接の子である Drug 要素のみを取得するには、childNodes属性を使用する必要があります。

于 2013-03-29T20:19:56.043 に答える
1

メモリ不足か何かでおかしなことが起きているのではないかと思い、ドラッグごとにイテレータを使ってパーサーを書き直して試してみたところ、例外を発生させずにプログラムが完了しました。

基本的にここで行っているのは、XML ファイル全体をメモリにロードする代わりに、各<drug>and</drug>タグの開始と終了について XML ファイルを解析することです。次に、毎回 minidom でそれを解析します。

<drug>それぞれの と の</drug>ペアがそれぞれの行にあると想定しているため、コードは少し壊れやすいかもしれません。うまくいけば、それは害を及ぼす以上に役立ちます。

#!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/ です。

于 2013-03-29T19:44:39.980 に答える