通过'ElementTree'在Python中用命名空间解析XML

我有我想用Python的ElementTree解析的以下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有多个嵌套命名空间,所以我仍然无法实现这个功能。

请让我知道如何更改代码来查找所有owl:Class标签。


ElementTree对命名空间不太聪明。 你需要给.find()findall()iterfind()方法一个明确的命名空间字典。 这没有很好记录:

namespaces = {'owl': 'http://www.w3.org/2002/07/owl#'} # add more as needed

root.findall('owl:Class', namespaces)

前缀只能在您传入的namespaces参数中查找。这意味着您可以使用任何您喜欢的名称空间前缀; 该API将拆分owl: part,在namespaces字典中查找相应的名称空间URL,然后更改搜索以查找XPath表达式{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函数,仅解析名称空间启动事件(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#'}

然后字典可以作为参数传递给搜索函数:

root.findall('owl:Class', my_namespaces)
链接地址: http://www.djcxy.com/p/58793.html

上一篇: Parsing XML with namespace in Python via 'ElementTree'

下一篇: Parsing XML in Python using ElementTree example