簡體   English   中英

我如何使用Python中的LXML捕獲XML文件的所有元素名稱?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM