通过“ElementTree”在Python中用命名空间parsingXML

我有我想用Python的ElementTreeparsing的以下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> 

希望这对未来的人有用