通过“ElementTree”在Python中用命名空间parsingXML
我有我想用Python的ElementTree
parsing的以下XML:
<rdf:RDF xml:base="http://dbpedia.org/ontology/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns="http://dbpedia.org/ontology/"> <owl:Class rdf:about="http://dbpedia.org/ontology/BasketballLeague"> <rdfs:label xml:lang="en">basketball league</rdfs:label> <rdfs:comment xml:lang="en"> a group of sports teams that compete against each other in Basketball </rdfs:comment> </owl:Class> </rdf:RDF>
我想查找所有owl:Class
标签,然后提取其中所有rdfs:label
实例的值。 我正在使用下面的代码:
tree = ET.parse("filename") root = tree.getroot() root.findall('owl:Class')
由于命名空间,我收到以下错误。
SyntaxError: prefix 'owl' not found in prefix map
我尝试阅读文档在http://effbot.org/zone/element-namespaces.htm,但我仍然无法得到这个工作,因为上面的XML有多个嵌套的命名空间。
请让我知道如何改变代码来find所有的owl:Class
标签。
ElementTree对命名空间不太聪明。 你需要给.find()
, findall()
和iterfind()
方法一个明确的命名空间字典。 这没有很好的logging:
namespaces = {'owl': 'http://www.w3.org/2002/07/owl#'} # add more as needed root.findall('owl:Class', namespaces)
前缀只能在传入的namespaces
参数中查找。这意味着您可以使用任何您喜欢的名称空间前缀; 该API分离owl:
part,在namespaces
字典中查找相应的名称空间URL,然后更改search以查找XPathexpression式{http://www.w3.org/2002/07/owl}Class
。 当然你也可以使用相同的语法:
root.findall('{http://www.w3.org/2002/07/owl#}Class')
如果你可以切换到lxml
库,事情会更好; 该库支持相同的ElementTree API,但在元素上的.nsmap
属性中为您收集名称空间。
以下是如何使用lxml完成此操作,而不必对命名空间进行硬编码或扫描文本(如Martijn Pieters所述):
from lxml import etree tree = etree.parse("filename") root = tree.getroot() root.findall('owl:Class', root.nsmap)
注意 :这是一个对Python的ElementTree标准库有用的答案,不需要使用硬编码的命名空间。
要从XML数据中提取名称空间的前缀和URI,可以使用ElementTree.iterparse
函数,仅parsing名称空间开始事件( start-ns ):
>>> from io import StringIO >>> from xml.etree import ElementTree >>> my_schema = u'''<rdf:RDF xml:base="http://dbpedia.org/ontology/" ... xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ... xmlns:owl="http://www.w3.org/2002/07/owl#" ... xmlns:xsd="http://www.w3.org/2001/XMLSchema#" ... xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" ... xmlns="http://dbpedia.org/ontology/"> ... ... <owl:Class rdf:about="http://dbpedia.org/ontology/BasketballLeague"> ... <rdfs:label xml:lang="en">basketball league</rdfs:label> ... <rdfs:comment xml:lang="en"> ... a group of sports teams that compete against each other ... in Basketball ... </rdfs:comment> ... </owl:Class> ... ... </rdf:RDF>''' >>> my_namespaces = dict([ ... node for _, node in ElementTree.iterparse( ... StringIO(my_schema), events=['start-ns'] ... ) ... ]) >>> from pprint import pprint >>> pprint(my_namespaces) {'': 'http://dbpedia.org/ontology/', 'owl': 'http://www.w3.org/2002/07/owl#', 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdfs': 'http://www.w3.org/2000/01/rdf-schema#', 'xsd': 'http://www.w3.org/2001/XMLSchema#'}
然后,字典可以作为parameter passing给searchfunction:
root.findall('owl:Class', my_namespaces)
我一直在使用类似的代码,并发现它总是值得阅读文档…像往常一样!
findall()只会查找当前标签的直接子元素。 所以,不是全部。
如果你正在处理大而复杂的xml文件,这样子子元素(等等)也被包含在内,这可能是值得的。 如果你知道你的xml中的元素是什么,那么我认为它会好起来的! 只是觉得这值得记住。
root.iter()
ref: https : //docs.python.org/3/library/xml.etree.elementtree.html#finding-interesting-elements “Element.findall()仅查找带有标签的元素,它们是当前元素的直接子元素。 Element.find()find第一个具有特定标签的子元素,Element.text访问元素的文本内容,Element.get()访问元素的属性:“
我知道我晚了几年,但我刚刚创build了一个包,将处理将字典转换为有效的XML与名称空间。 该软件包位于PyPi @ https://pypi.python.org/pypi/xmler上; 。
使用这个包,你可以看一下这样的字典:
myDict = { "RootTag": { # The root tag. Will not necessarily be root. (see #customRoot) "@ns": "soapenv", # The namespace for the RootTag. The RootTag will appear as <soapenv:RootTag ...> "@attrs": { # @attrs takes a dictionary. each key-value pair will become an attribute { "xmlns:soapenv": "http://schemas.xmlsoap.org/soap/envelope/" } }, "childTag": { "@attrs": { "someAttribute": "colors are nice" }, "grandchild": "This is a text tag" } } }
并获得如下所示的XML输出:
<soapenv:RootTag xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <childTag someAttribute="colors are nice"> <grandchild>This is a text tag</grandchild> </childTag> </soapenv:RootTag>
希望这对未来的人有用