使用pythonlxml处理嵌套元素
给出以下简单的XML数据:使用pythonlxml处理嵌套元素,python,xml,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>
<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>
我试图遵循,但上面的代码没有按预期工作
在另一种情况下,最好能够将整个XML树读入Python字典,每个元素作为键,每个文本作为元素项。我发现使用lxml objectify可以实现类似的功能,但我不知道如何实现它
在尝试用Python编写XML解析代码时,我发现一个真正的大问题是,提供的大多数“示例”都太简单,而且完全是虚构的,没有太多帮助——或者它们正好相反,使用了太复杂的自动生成的XML数据
谁能给我一个提示吗
提前谢谢
编辑:发布这个问题后,我找到了一个简单的解决方案
因此,我的更新代码变成:
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
这非常简单,使用: 输出:
['First paragraph of the abstract', 'Second paragraph of the abstract']
['First keyword', 'Second keyword', 'Third keyword']
有关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
实际上代表root.abstract.para[0]
。因此,您需要显式使用element.iterchildren()
来访问所有子元素
事实并非如此,我们显然都误解了Objectify API:
为了在
abstract
中迭代para
,您需要迭代root.abstract.para
,而不是root.abstract
本身。这很奇怪,因为您直观地将抽象
视为其节点的集合或容器,而该容器将由Python iterable表示。但实际上,代表序列的是.para
选择器。当然,好提示!但是,使用lxml objectfy是否也能达到同样的结果呢?毫无疑问,这是可能的。但特别是对于要遍历树的(深度)嵌套结构,XPath通常更容易阅读。虽然有objectify.ObjectPath,但提供的示例有点难看…:-(@user40893使用Objectify API更新了我的答案。请注意,尽管在您问题的解决方案中,para
实际上不是一个字符串,但它是一个StringElement
对象。如果您打印它,它看起来像一个字符串,但取决于您以后对它所做的操作,您可能需要访问实际的st使用para.text
来响铃内容。事实上,下面的@LukasGraf answer也提供了同样的解决方案,但使用的方式更像python!:-)
['First paragraph of the abstract', 'Second paragraph of the abstract']
['First keyword', 'Second keyword', 'Third keyword']
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