python - 使用 Python lxml 处理嵌套元素

标签 python xml lxml

给定以下简单的 XML 数据:

<book>
   <title>My First Book</title>
   <abstract>
         <para>First paragraph of the abstract</para>
         <para>Second paragraph of the abstract</para>
    </abstract>
    <keywordSet>
         <keyword>First keyword</keyword>
         <keyword>Second keyword</keyword>
         <keyword>Third keyword</keyword>
    </keywordSet>
</book>

我如何遍历树,使用 lxml , 并获取“abstract”元素中的所有段落,以及“keywordSet”元素中的所有关键字?

下面的代码片段仅返回每个元素中的第一行文本:

from lxml import objectify
root = objectify.fromstring(xml_string) # xml_string contains the XML data above
print root.title # returns the book title
for line in root.abstract:
    print line.para # returns only yhe first paragraph
for word in root.keywordSet:
    print word.keyword # returns only the first keyword in the set

我试着关注 this example ,但上面的代码没有按预期工作。

换一种方式,更好的办法是将整个 XML 树读入 Python 字典,将每个元素作为键,将每个文本作为元素项。我发现使用 lxml objectify 可能会实现类似的功能,但我不知道如何实现它。

我在尝试用 Python 编写 XML 解析代码时发现的一个非常大的问题是,所提供的大多数“示例”都太简单而且完全是虚构的,没有多大帮助——否则它们恰恰相反, 使用过于复杂的自动生成的 XML 数据!

有人可以给我提示吗?

提前致谢!

编辑:发布这个问题后,我找到了一个简单的解决方案 here .

所以,我更新后的代码变成了:

from lxml import objectify
    root = objectify.fromstring(xml_string) # xml_string contains the XML data above
    print root.title # returns the book title
    for para in root.abstract.iterchildren():
        print para # now returns the text of all paragraphs
    for keyword in root.keywordSet.iterchildren():
        print keyword # now returns all keywords in the set

最佳答案

使用 XPath 非常简单:

from lxml import etree

tree = etree.parse('data.xml')

paragraphs = tree.xpath('/abstract/para/text()')
keywords = tree.xpath('/keywordSet/keyword/text()')

print paragraphs
print keywords

输出:

['First paragraph of the abstract', 'Second paragraph of the abstract']
['First keyword', 'Second keyword', 'Third keyword']

参见 the XPath Tutorial at W3Schools有关 XPath 语法的详细信息。

特别是上面表达式中使用的元素

  • 用于选择根节点/直接子节点的/选择器。
  • 用于选择各个元素的文本节点(“文本内容”)的 text() 运算符。

这是使用 Objectify API 实现的方法:

from lxml import objectify

root = objectify.fromstring(xml_string)

paras = [p.text for p in root.abstract.para]
keywords = [k.text for k in root.keywordSet.keyword]

print paras
print keywords

看起来root.abstract.para实际上是shorthand对于 root.abstract.para[0]。因此,您需要明确使用 element.iterchildren() 来访问所有子元素。

这不是真的,我们显然都误解了 Objectify API: 为了遍历 abstract 中的 para,您需要遍历 root.abstract.para,而不是 root.abstract 本身。这很奇怪,因为您直观地将 abstract 视为其节点的集合或容器,而该容器将由 Python 可迭代对象表示。但它实际上是表示序列的 .para 选择器。

关于python - 使用 Python lxml 处理嵌套元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26370098/

相关文章:

python - 在 python 2.6 中使用 XML API findall() 时出错

python - lxml xpath 返回一个空列表

python - 如何在 Python 中使用 lxml.html.clean.Cleaner() 保留内联 CSS 样式?

python - Django Admin 如何更改关系字段中的文本

python - 仅保留远距离值的高效算法

java - 从 POJO 生成 SOAP XML

python - BeautifulSoup 和 lxml 找不到 div 元素

python - 无法使用 Python 中的检查通过 exec 获取方法 "declared"的源代码

python - Microsoft Python 语言服务器无法识别 `for` 循环 `zip()`

java - 不同的spring配置文件角色