鉴于以下简单的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遍历树,并获取&#34; abstract&#34;中的所有段落。元素,以及&#34; keywordSet&#34;中的所有关键字;元件?
下面的代码片段仅返回每个元素中的第一行文字:
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解析代码时发现的一个非常大的问题是大多数&#34;示例&#34;提供的内容过于简单且完全虚构,无法提供太多帮助 - 否则它们恰恰相反,使用过于复杂的自动生成的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
答案 0 :(得分:6)
使用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']
有关XPath语法的详细信息,请参阅the XPath Tutorial at W3Schools。
特别是,上述表达式中使用的元素
/
选择器,用于选择根节点/直接子节点。text()
运算符,用于选择相应元素的文本节点(&#34;文本内容&#34;)。以下是使用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]
似乎实际为shorthand。因此,您需要明确使用element.iterchildren()
来访问所有子元素。
这不是真的,我们显然都误解了Objectify API:
为了迭代para
中的abstract
,您需要迭代root.abstract.para
,而不是root.abstract
。这很奇怪,因为您直观地将abstract
视为其节点的集合或容器,并且该容器将由Python可迭代表示。但它实际上是代表序列的.para
选择器。