Sud*_*dar 148 python xml elementtree xml-namespaces xml-parsing
我有以下XML,我想用Python解析ElementTree
:
<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>
Run Code Online (Sandbox Code Playgroud)
我想找到所有owl:Class
标签,然后提取其中所有rdfs:label
实例的值.我使用以下代码:
tree = ET.parse("filename")
root = tree.getroot()
root.findall('owl:Class')
Run Code Online (Sandbox Code Playgroud)
由于命名空间,我收到以下错误.
SyntaxError: prefix 'owl' not found in prefix map
Run Code Online (Sandbox Code Playgroud)
我尝试在http://effbot.org/zone/element-namespaces.htm上阅读该文档,但由于上述XML具有多个嵌套命名空间,因此我仍然无法正常工作.
请告诉我如何更改代码以查找所有owl:Class
标签.
Mar*_*ers 210
ElementTree对名称空间并不太聪明.您需要为.find()
,findall()
和iterfind()
方法提供显式命名空间字典.这没有记录得很好:
namespaces = {'owl': 'http://www.w3.org/2002/07/owl#'} # add more as needed
root.findall('owl:Class', namespaces)
Run Code Online (Sandbox Code Playgroud)
只在namespaces
您传入的参数中查找前缀.这意味着您可以使用任何您喜欢的命名空间前缀; API拆分owl:
部件,在namespaces
字典中查找相应的命名空间URL ,然后更改搜索以查找XPath表达式{http://www.w3.org/2002/07/owl}Class
.当然,您也可以自己使用相同的语法:
root.findall('{http://www.w3.org/2002/07/owl#}Class')
Run Code Online (Sandbox Code Playgroud)
如果你可以切换到lxml
图书馆,事情会更好; 该库支持相同的ElementTree API,但.nsmap
在元素的属性中为您收集名称空间.
Bra*_*Dre 55
以下是如何使用lxml执行此操作而无需对命名空间进行硬编码或扫描文本(如Martijn Pieters所提到的):
from lxml import etree
tree = etree.parse("filename")
root = tree.getroot()
root.findall('owl:Class', root.nsmap)
Run Code Online (Sandbox Code Playgroud)
Dav*_*ato 25
注意:这是一个对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#'}
Run Code Online (Sandbox Code Playgroud)
然后字典可以作为参数传递给搜索函数:
root.findall('owl:Class', my_namespaces)
Run Code Online (Sandbox Code Playgroud)
要以命名空间格式获取命名空间,例如{myNameSpace}
,您可以执行以下操作:
root = tree.getroot()
ns = re.match(r'{.*}', root.tag).group(0)
Run Code Online (Sandbox Code Playgroud)
这样,您可以稍后在代码中使用它来查找节点,例如使用字符串插值(Python 3)。
link = root.find(f"{ns}link")
Run Code Online (Sandbox Code Playgroud)
我一直在使用类似的代码,并发现它总是值得阅读文档...像往常一样!
findall()只会找到当前标记的直接子元素.所以,不是全部.
在尝试使用以下代码时,可能值得您使用,特别是如果您正在处理大而复杂的xml文件,以便还包括子子元素(等).如果你知道你的xml中的元素在哪里,那么我想它会没事的!只是觉得这值得记住.
root.iter()
Run Code Online (Sandbox Code Playgroud)
ref:https://docs.python.org/3/library/xml.etree.elementtree.html#finding-interesting-elements "Element.findall()仅查找带有标签的元素,这些元素是当前元素的直接子元素. Element.find()查找具有特定标记的第一个子元素,Element.text访问元素的文本内容.Element.get()访问元素的属性:"
归档时间: |
|
查看次数: |
117432 次 |
最近记录: |