首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在lxml中通过find/findall使用xml名称空间?

如何在lxml中通过find/findall使用xml名称空间?
EN

Stack Overflow用户
提问于 2010-11-18 09:07:30
回答 3查看 31.5K关注 0票数 33

我正在尝试解析OpenOffice ODS电子表格中的内容。ods格式本质上只是一个包含多个文档的zipfile。电子表格的内容存储在“content.xml”中。

代码语言:javascript
复制
import zipfile
from lxml import etree

zf = zipfile.ZipFile('spreadsheet.ods')
root = etree.parse(zf.open('content.xml'))

电子表格的内容在单元格中:

代码语言:javascript
复制
table = root.find('.//{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table')

我们也可以直接使用行:

代码语言:javascript
复制
rows = root.findall('.//{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-row')

各个元素知道名称空间:

代码语言:javascript
复制
>>> table.nsmap['table']
'urn:oasis:names:tc:opendocument:xmlns:table:1.0'

如何在find/findall中直接使用名称空间?

显而易见的解决方案不起作用。

尝试从表中获取行:

代码语言:javascript
复制
>>> root.findall('.//table:table')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lxml.etree.pyx", line 1792, in lxml.etree._ElementTree.findall (src/lxml/lxml.etree.c:41770)
  File "lxml.etree.pyx", line 1297, in lxml.etree._Element.findall (src/lxml/lxml.etree.c:37027)
  File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 225, in findall
    return list(iterfind(elem, path))
  File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 200, in iterfind
    selector = _build_path_iterator(path)
  File "/usr/lib/python2.6/dist-packages/lxml/_elementpath.py", line 184, in _build_path_iterator
    selector.append(ops[token[0]](_next, token))
KeyError: ':'
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-11-18 09:39:21

如果root.nsmap包含table名称空间前缀,那么您可以:

代码语言:javascript
复制
root.xpath('.//table:table', namespaces=root.nsmap)

findall(path)接受{namespace}name语法,而不是namespace:name。因此,在将path传递给findall()之前,应该使用名称空间字典将其预处理为{namespace}name表单。

票数 26
EN

Stack Overflow用户

发布于 2013-12-20 02:34:07

下面是获取XML文档中所有名称空间的方法(假设没有前缀冲突)。

当我预先知道名称空间URL是什么,并且只知道前缀时,我就会在解析XML文档时使用它。

代码语言:javascript
复制
        doc = etree.XML(XML_string)

        # Getting all the name spaces.
        nsmap = {}
        for ns in doc.xpath('//namespace::*'):
            if ns[0]: # Removes the None namespace, neither needed nor supported.
                nsmap[ns[0]] = ns[1]
        doc.xpath('//prefix:element', namespaces=nsmap)
票数 11
EN

Stack Overflow用户

发布于 2018-08-31 02:29:05

如果XML文件中没有xmlns定义,Etree将找不到带名称空间的元素。例如:

代码语言:javascript
复制
import lxml.etree as etree

xml_doc = '<ns:root><ns:child></ns:child></ns:root>'

tree = etree.fromstring(xml_doc)

# finds nothing:
tree.find('.//ns:root', {'ns': 'foo'})
tree.find('.//{foo}root', {'ns': 'foo'})
tree.find('.//ns:root')
tree.find('.//ns:root')

有时这就是你得到的数据。那么,如果没有名称空间,该怎么办呢?

我的解决方案是:添加一个。

代码语言:javascript
复制
import lxml.etree as etree

xml_doc = '<ns:root><ns:child></ns:child></ns:root>'
xml_doc_with_ns = '<ROOT xmlns:ns="foo">%s</ROOT>' % xml_doc

tree = etree.fromstring(xml_doc_with_ns)

# finds what you're looking for:
tree.find('.//{foo}root')
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4210730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档