[英]How I do capture all of the element names of an XML file using LXML in Python?
我能够使用lxml来完成我想做的大部分工作,尽管通过模糊的示例和教程很难。 简而言之,我能够读取外部xml文件并通过lxml将其导入到适当的树状格式中。
为了证明这一点,如果我输入:
print(etree.tostring(myXmlTree, pretty_print= True, method= "xml") )
我得到以下输出:
<net xmlns="http://www.arin.net/whoisrws/core/v1" xmlns:ns2="http://www.arin.net/whoisrws/rdns/v1" xmlns:ns3="http://www.arin.net/whoisrws/netref/v2" termsOfUse="https://www.arin.net/whois_tou.html">
<registrationDate>2006-08-29T00:00:00-04:00</registrationDate>
<ref>http://whois.arin.net/rest/net/NET-79-0-0-0-1</ref>
<endAddress>79.255.255.255</endAddress>
<handle>NET-79-0-0-0-1</handle>
<name>79-RIPE</name>
<netBlocks>
<netBlock>
<cidrLength>8</cidrLength>
<endAddress>79.255.255.255</endAddress>
<description>Allocated to RIPE NCC</description>
<type>RN</type>
<startAddress>79.0.0.0</startAddress>
</netBlock>
</netBlocks>
<orgRef name="RIPE Network Coordination Centre" handle="RIPE">http://whois.arin.net/rest/org/RIPE</orgRef>
<comment>
<line number="0">These addresses have been further assigned to users in</line>
<line number="1">the RIPE NCC region. Contact information can be found in</line>
<line number="2">the RIPE database at http://www.ripe.net/whois</line>
</comment>
<startAddress>79.0.0.0</startAddress>
<updateDate>2009-05-18T07:34:02-04:00</updateDate>
<version>4</version>
</net>
好的,这对人类消费很有用,但对机器没用。 如果我想要特殊的元素,比如说xml中的起始和结束IP地址,我可以输入:
ns = myXmlTree.nsmap.values()[0]
myXmlTree.findall("{" + ns + "}startAddress")[0].text
myXmlTree.findall("{" + ns + "}endAddress")[0].text
我会收到:
'79.0.0.0'
'79.255.255.255'
但是我仍然需要将xml文件看作是一个人来知道那里有哪些元素。 相反,我希望能够检索特定级别的所有元素的名称,然后自动遍历该级别。 所以,举例来说,我想做的事情如下:
myElements = myXmlTree.findallelements("{" + ns + "}")
它会给我一个返回值,如:
['registrationDate', 'ref', 'endAddress', 'handle', 'name', 'netBlocks', 'orgRef', 'comment', 'startAddress', 'updateDate', 'version']
特别棒的是它能告诉我整个元素结构,包括嵌套元素。
我确实有办法,否则就没有意义了。
提前致谢!!
PS,我知道我可以迭代并浏览所有迭代的列表。 我希望lxml中已经存在一个包含这些数据的方法。 如果迭代是唯一的方法,我想这没关系...它对我来说似乎很笨拙。
我相信你正在寻找element.xpath()
。
XPath不是lxml
引入的概念,而是一种通用查询语言,用于从许多处理XML的事物支持的XML文档中选择节点。 可以把它想象成与CSS选择器类似的东西,但功能更强大(也有点复杂)。 请参阅XPath语法 。
您的文档使用命名空间 - 我现在将忽略它并在帖子的末尾解释如何处理它们,因为它使示例更具可读性。 (但它们不会按原样用于您的文档)。
所以,例如,
tree.xpath('/net/endAddress')
将在<net />
节点下方直接选择<endAddress>79.255.255.255</endAddress>
元素。 但不是<endAddress />
的<endAddress />
<netBlock>
。
XPath表达式
tree.xpath('//endAddress')
但是会在文档中的任何位置选择所有<endAddress />
节点。
您当然可以使用XPath epxressions进一步查询您获得的节点:
netblocks = tree.xpath('/net/netBlocks/netBlock')
for netblock in netblocks:
start = netblock.xpath('./startAddress/text()')[0]
end = netblock.xpath('./endAddress/text()')[0]
print "%s - %s" % (start, end)
会给你的
79.0.0.0 - 79.255.255.255
请注意, .xpath()
始终返回所选节点的列表 - 因此,如果您只想要一个节点,请.xpath()
该节点。
您还可以按属性选择元素:
comment = tree.xpath('/net/comment')[0]
line_2 = comment.xpath("./line[@number='2']")[0]
这将从第一个注释中选择number="2"
的<line />
元素。
您也可以自己选择属性:
numbers = tree.xpath('//line/attribute::number')
['0', '1', '2']
要获取最后询问的元素名称列表,您可以执行以下操作:
names = [node.tag for node in tree.xpath('/net/*')]
['registrationDate', 'ref', 'endAddress', 'handle', 'name', 'netBlocks', 'orgRef', 'comment', 'startAddress', 'updateDate', 'version']
但是考虑到XPath的强大功能,最好只查询文档中您想要了解的内容,如您认为的那样具体或松散。
现在,名称空间。 正如您所注意到的,如果您的文档使用XML命名空间,则需要在许多地方考虑这一点,并且XPath也不例外。 查询命名空间文档时,将xpath()
方法传递给命名空间映射,如下所示:
NSMAP = {'ns': 'http://www.arin.net/whoisrws/core/v1',
'ns2': 'http://www.arin.net/whoisrws/rdns/v1',
'ns3': 'http://www.arin.net/whoisrws/netref/v2'}
names = [node.tag for node in tree.xpath('/ns:net/*', namespaces=NSMAP)]
在lxml
许多其他位置,您可以使用None
作为命名空间映射中的字典键来设置默认命名空间。 不幸的是,不会使用xpath()
,这将引发异常
TypeError: empty namespace prefix is not supported in XPath
因此,您不得不使用ns:
或您选择将该命名空间映射到的任何地方)为XPath表达式中的每个节点名称添加前缀。
有关XPath语法的更多信息,请参阅W3Schools Xpath教程中的XPath语法页面。
要开始使用XPath,在许多XPath测试人员中调整文档也非常有用。 此外,Firefox的Firebug插件或Google Chrome检查器允许您显示所选元素的(或更确切地说,多个)XPath。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.