我正在寻找一种从非常大的xml文档中获取特定标签的方法
用python dom内置模块
例如:
<AssetType longname="characters" shortname="chr" shortnames="chrs">
<type>
pub
</type>
<type>
geo
</type>
<type>
rig
</type>
</AssetType>
<AssetType longname="camera" shortname="cam" shortnames="cams">
<type>
cam1
</type>
<type>
cam2
</type>
<type>
cam4
</type>
</AssetType>
我想检索获得属性的AssetType节点的子节点的值(longname =“characters”)
得到'pub','geo','rig'
的结果
请记住,我有超过1000&lt; AssetType&GT;节点
提前谢谢
答案 0 :(得分:5)
假设您的文档名为assets.xml
并具有以下结构:
<assets>
<AssetType>
...
</AssetType>
<AssetType>
...
</AssetType>
</assets>
然后您可以执行以下操作:
from xml.etree.ElementTree import ElementTree
tree = ElementTree()
root = tree.parse("assets.xml")
for assetType in root.findall("//AssetType[@longname='characters']"):
for type in assetType.getchildren():
print type.text
答案 1 :(得分:3)
您可以使用pulldom API来处理解析大文件,而无需立即将其全部加载到内存中。这提供了比使用SAX更方便的界面,只有轻微的性能损失。
它基本上允许您流式传输xml文件,直到找到您感兴趣的位,然后在此之后开始使用regular DOM operations。
from xml.dom import pulldom
# http://mail.python.org/pipermail/xml-sig/2005-March/011022.html
def getInnerText(oNode):
rc = ""
nodelist = oNode.childNodes
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
elif node.nodeType==node.ELEMENT_NODE:
rc = rc + getInnerText(node) # recursive !!!
elif node.nodeType==node.CDATA_SECTION_NODE:
rc = rc + node.data
else:
# node.nodeType: PROCESSING_INSTRUCTION_NODE, COMMENT_NODE, DOCUMENT_NODE, NOTATION_NODE and so on
pass
return rc
# xml_file is either a filename or a file
stream = pulldom.parse(xml_file)
for event, node in stream:
if event == "START_ELEMENT" and node.nodeName == "AssetType":
if node.getAttribute("longname") == "characters":
stream.expandNode(node) # node now contains a mini-dom tree
type_nodes = node.getElementsByTagName('type')
for type_node in type_nodes:
# type_text will have the value of what's inside the type text
type_text = getInnerText(type_node)
答案 2 :(得分:2)
使用xml.sax模块。构建自己的处理程序,在startElement内部,您应该检查名称是否为AssetType。这样,您应该只能在处理AssetType节点时执行操作。
Here你有示例处理程序,它显示了如何构建一个(虽然它不是最漂亮的方式,在那一点上我不知道Python的所有很酷的技巧; - ))。
答案 3 :(得分:2)
如果您不介意将整个文档加载到内存中:
from lxml import etree
data = etree.parse(fname)
result = [node.text.strip()
for node in data.xpath("//AssetType[@longname='characters']/type")]
您可能需要删除代码开头的空格才能使其正常工作。
答案 4 :(得分:1)
您可以使用xpath,例如“// AssetType [longname ='characters'] / xyz”。
对于Python中的XPath库,请参阅http://www.somebits.com/weblog/tech/python/xpath.html
答案 5 :(得分:1)
与eswald的解决方案类似,再次剥离空白,再次将文档加载到内存中,但一次返回三个文本项
from lxml import etree
data = """<AssetType longname="characters" shortname="chr" shortnames="chrs"
<type>
pub
</type>
<type>
geo
</type>
<type>
rig
</type>
</AssetType>
"""
doc = etree.XML(data)
for asset in doc.xpath('//AssetType[@longname="characters"]'):
threetypes = [ x.strip() for x in asset.xpath('./type/text()') ]
print threetypes