Python:使用小型dom通过XML进行解析
我正在解析一个相当大的xml文件,遇到了一个问题。由于某种原因,我无法提取数据,即使我以前在不同的xml文件上做过完全相同的事情 下面是我的一段代码:(程序的其余部分,我已经测试过了,它们工作得很好) 编辑:更改为包含测试尝试块(&E)Python:使用小型dom通过XML进行解析,python,xml,parsing,text-parsing,Python,Xml,Parsing,Text Parsing,我正在解析一个相当大的xml文件,遇到了一个问题。由于某种原因,我无法提取数据,即使我以前在不同的xml文件上做过完全相同的事情 下面是我的一段代码:(程序的其余部分,我已经测试过了,它们工作得很好) 编辑:更改为包含测试尝试块(&E) def parseXML(): file = open(str(options.drugxml),'r') data = file.read() file.close() dom = parseString(data) d
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文件工作过,不确定为什么它不能在这个文件上工作。我在“type”上得到了KeyError,在提取药物ID的行上也得到了索引错误,即使每个药物都有一个药物ID。我搞砸了什么
编辑:我提取的东西保证在每种药物中
对于任何关心此事的人,这里是指向我正在解析的XML文件的链接:
编辑:在实现try&except块(见上文)后,我发现:
在模式中,有一些称为“药物相互作用”的部分,也有一个称为药物的子字段。所以像这样:
<drugs>
<drug type='something' ...>
<drugbank-id>
<name>
...
<targets>
<target partner='something'>
<drug-interactions>
<drug>
...
我认为我的行druglist=dom.getElementsByTagName('Druge')也无意中拾取了这些内容--我不知道如何修复此问题。。。有什么建议吗?我有一种感觉,可能是由于内存不足或其他原因而发生了一些奇怪的事情,所以我使用迭代器对每种药物重写了解析器,并进行了尝试,让程序在没有引发异常的情况下完成 基本上,我在这里做的是,不将整个XML文件加载到内存中,而是解析每个
和
标记的开头和结尾的XML文件。然后每次我都用minidom解析它
代码可能有点脆弱,因为我假设每个
和
对都在各自的行中。希望它能帮助你,而不是伤害你
#!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')
#!python
导入编解码器
从xml.dom导入minidom
类别银行(对象):
def uuu init uuu(self,文件名):
self.fp=open(文件名'r')
定义(自我):
回归自我
def next(自我):
状态=0
尽管如此:
line=self.fp.readline()
如果state==0:
如果line.strip().startswith('基本上是在xml中使用时,那么您不能依赖于您知道结构这一事实。在代码中查找结构是一种很好的做法
因此,每次访问元素或属性时,请先检查是否有。在代码中,它表示以下内容:
确保药物元素上有属性“type”:
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
此外,在访问childnodes之前,请确保存在以下内容:
if drugidObj.hasChildNodes:
drugid = drugidObj.childNodes[0].nodeValue
或者使用for循环来循环它们
当您在Druges元素上调用getElementsByTagName
时,它会返回所有元素,包括嵌套的元素。要仅获取Druge元素,即drugs元素的直接子元素,您必须使用childNodes
属性。是否可以包含错误的堆栈跟踪?是的,经过编辑,以使最近的两个错误除了添加/删除打印语句之外,在没有进行太多更改的情况下遇到。您的代码假定记录始终具有您认为它们具有的格式。KeyError只是意味着drug元素没有类型属性。Indexer出现类似问题…记录没有您想要的信息。请尝试在druglist中输入“for entry:”将块放入try/except块中,然后打印导致问题的条目。它看起来正确吗?从长远来看,except处理程序会实现您的失败策略(继续处理、报告记录或其他)@tdelaney一开始我认为这可能是导致错误的原因,但当我检查数据时,每个药物字段都有一个type属性,每个药物都必须有一个药物id和药物名称。我甚至用数据源检查了这一点。他们中的每一个都必须在那里。这就是我被难住的原因。我将放入try/except块并制作一些更多检查。@Joe If drugs是根元素,它只有Druge,因为后续元素在drugs上使用childNodes而不是getElementsByTagName。很好,我会看一看。我最终也自己解决了这个问题,但我也会尝试一下。谢谢!