2016-09-19 57 views
-1

抱歉,如果標題不說清楚,我正在解析有大量的嵌套的標籤的XML文件,例如有云:Python的XML解析 - 如果元素==「值」做X

<Artifacts> 
<Artifact name="1"> 
    <Fragments> 
    <hits> 
    <hit sequence="1"> 
    <Fragment name="1">Data</Fragment> 
    <Fragment name="2">Data</Fragment> 
    </hit> 
    </hits> 
    </Fragments> 
</Artifact> 
<Artifact name="2"> 

(讓版面更清晰抱歉) 等等。我目前所受的痛苦就是隻能得到我們需要的數據。從上面的示例中,我們需要Artifact name = 1下的所有內容,並將Data的片段名稱「1」拉出。目標結果如下:

工件=「1」,片段名稱=「1」,片段數據=「數據」。

目前我似乎無法理解它,我已經完成類似於PHP沒有問題,但這需要在Python中完成。

所以有點抱歉抱歉,但沒有人有任何想法如何指定只抓取來自名爲1,3,5的工件的數據,例如忽略其他所有內容?我所能做的就是從文件中的所有內容中抓取它(這會降低速度,然後需要進一步處理)

謝謝。

+4

你聽說過的XPath?安裝[lxml](http://lxml.de/xpathxslt.html#the-xpath-method]並搜索匹配'「/ Artifacts/Artifact [@name ='1'或@name ='3'或@name的元素='5']「',例如, –

+0

@LaurentLAPORTE或'[@name =('1','3','5')]';在XPath中,'='實際上是查找集合交集 –

+1

@Charles Duffy:哪個版本的XPath?我從來沒有聽說過,它一定是最近的變化,但'lxml'不喜歡它:'tree.xpath(「/ Artifacts/Artifact [@name =('1 ','3','5')]「)'raise'lxml.etree.XPathEvalError:Invalid expression'。 –

回答

1

隨着minidom命名:

from xml.dom import minidom 

xmlstr = ''' 
<Artifacts> 
<Artifact name="1"> 
<Fragments> 
<Fragment name="1">Data</Fragment> 
</Fragments> 
</Artifact> 
<Artifact name="2"> 
</Artifact> 
</Artifacts> 
''' 


def with_children(tag): 
    if tag.localName: # if not, it's text node 
     print tag.localName, 
     if tag.hasAttributes(): 
      for item in tag.attributes.items(): 
       print "%s=%s" % item, 

     for child in tag.childNodes: 
      with_children(child) 

    else: 
     s = tag.nodeValue.strip() 
     print "data=%s" % s if s else "", 

xml = minidom.parseString(xmlstr) 
tags = xml.getElementsByTagName('Artifact') 
tag = [t for t in tags if t.attributes['name'].value == '1'][0] 
with_children(tag) 
+0

非常感謝:)我以前使用minidom,所以這適合更多我以前(有點),並一直試圖。將嘗試和調整這個以滿足我更多的需求,因爲最終的結果是更改XML文件的格式以允許導入到另一個系統。 有沒有辦法做搜索,然後保持XML格式能夠循環通過它來獲取所需的數據? 只抓住'數據',因爲這將稍後需要更改爲xml格式有點像「數據」等? –

+0

有minidom.getDOMImplementation來創建文檔和節點。 – theit

1

下面是使用lxml一個簡單的例子:

from lxml import etree 

content = '''\ 
<Artifacts> 
    <Artifact name="1"> 
    <Fragments> 
     <Fragment name="1">Data</Fragment> 
    </Fragments> 
    </Artifact> 
    <Artifact name="2"> 
    <Fragments> 
     <Fragment name="2">Data2</Fragment> 
    </Fragments> 
    </Artifact> 
    <Artifact name="3"> 
    <Fragments> 
     <Fragment name="3">Data3</Fragment> 
    </Fragments> 
    </Artifact> 
</Artifacts> 
''' 

tree = etree.XML(content) 

elts = tree.xpath("/Artifacts/Artifact[@name = '1' or @name = '3' or @name = '5']") 

for elt in elts: 
    etree.dump(elt) 

您將獲得:

<Artifact name="1"> 
    <Fragments> 
     <Fragment name="1">Data</Fragment> 
    </Fragments> 
    </Artifact> 

<Artifact name="3"> 
    <Fragments> 
     <Fragment name="3">Data3</Fragment> 
    </Fragments> 
    </Artifact> 

如果你想提取每個片段:

artifacts = tree.xpath("/Artifacts/Artifact[@name = '1' or @name = '3' or @name = '5']") 

fmt = 'Artifact = "{art_name}",' \ 
     'Fragment Name = "{frag_name}",' \ 
     'Fragment Data = "{data}".' 
for artifact in artifacts: 
    for fragments in artifact.iter("Fragments"): 
     for fragment in fragments.iter("Fragment"): 
      print(fmt.format(art_name=artifact.get("name"), 
          frag_name=fragment.get("name"), 
          data=fragment.text)) 

您將獲得:

Artifact = "1", Fragment Name = "1", Fragment Data = "Data". 
Artifact = "3", Fragment Name = "3", Fragment Data = "Data3".