2016-08-16 57 views
1

我的路徑和值的列表,像這樣:與路徑和值編寫XML

[ 
    {'Path': 'Item/Info/Name', 'Value': 'Body HD'}, 
    {'Path': 'Item/Genres/Genre', 'Value': 'Action'}, 
] 

而且我想打造出完整的XML結構,具體做法是:

<Item> 
    <Info> 
     <Name>Body HD</Name> 
    </Info> 
    <Genres> 
     <Genre>Action</Genre> 
    </Genres> 
</Item> 

有沒有辦法做到這一點lxml?或者我如何構建一個函數來填充推斷的路徑?

+0

那麼第一個節點在路徑中總是相同的? –

+0

@PadraicCunningham這是正確的 – David542

回答

1

你可以這樣做:

l = [ 
    {'Path': 'Item/Info/Name', 'Value': 'Body HD'}, 
    {'Path': 'Item/Genres/Genre', 'Value': 'Action'}, 
] 


import lxml.etree as et 
root_node = l[0]["Path"].split("/", 1)[0] 
tree = et.fromstring("<{}></{}>".format(root_node, root_node)) 


for dct in l:   
    nodes = iter(dct["Path"].split("/")[1:]) 
    # catch path like Item/Foo where there is only one child. 
    nxt_child = child = et.Element(next(nodes)) 
    for node in nodes: 
     # keep adding nodes 
     nxt_child = et.Element(node) 
     child.append(nxt_child) 
    # set value to last node. 
    nxt_child.text = dct["Value"] 
    # append it to the tree. 
    tree.append(child) 


print(et.tostring(tree)) 

這將使你:

<Item> 
    <Info> 
    <Name>Body HD</Name> 
    </Info> 
    <Genres> 
    <Genre>Action</Genre> 
    </Genres> 
</Item> 

你知道Item是根節點,並在每個路徑的第一,所以首先創建使用該樹節點,然後隨時添加到樹中。

+0

這是一個很好的方法,雖然我得到了'未定義分割'。 – David542

+0

我編輯拆分爲'nodes'。另外,我在這裏創建了另一個更復雜的問題,其中包含屬性等。 - http://stackoverflow.com/questions/38984272/generating-xml-from-list-of-path-values。 – David542

1

是的,你可以用lxml來做到這一點。

我建議你使用模板XML並填充它。

模板:

<Item> 
    <Info> 
     <Name/> 
    </Info> 
    <Genres> 
     <Genre/> 
    </Genres> 
</Item> 

from lxml import etree 

tree = etree.parse("template.xml") 

然後往裏面:

entries = [ 
    {'Path': 'Item/Info/Name', 'Value': 'Body HD'}, 
    {'Path': 'Item/Genres/Genre', 'Value': 'Action'}] 

for entry in entries: 
    xpath = entry["Path"] 
    node = tree.xpath(xpath)[0] 
    node.text = entry['Value'] 

注:不是 「路徑」,我更願意 「的XPath」

如果你不想要的模板,你可以像這樣產生整個樹形結構:

from lxml import etree 

entries = [ 
    {'Path': 'Item/Info/Name', 'Value': 'Body HD'}, 
    {'Path': 'Item/Genres/Genre', 'Value': 'Action'}] 

root = None 

for entry in entries: 
    path = entry["Path"] 
    parts = path.split("/") 
    xpath_list = ["/" + parts[0]] + parts[1:] 
    curr = root 
    for xpath in xpath_list: 
     name = xpath.strip("/") 
     if curr is None: 
      root = curr = etree.Element(name) 
     else: 
      nodes = curr.xpath(xpath) 
      if nodes: 
       curr = nodes[0] 
      else: 
       curr = etree.SubElement(curr, name) 
    curr.text = entry["Value"] 

print(etree.tostring(root, pretty_print=True)) 

結果是:

<Item> 
    <Info> 
    <Name>Body HD</Name> 
    </Info> 
    <Genres> 
    <Genre>Action</Genre> 
    </Genres> 
</Item> 

當然,也有侷限性。

+2

這並沒有真正回答這個問題。我沒有一個XML模板。我試圖建立它(雖然順便說一下,我沒有讓你失望,只是想讓你知道你的答案與問題無關)。 – David542

+0

我編輯我的答案,正如你所看到的,你可以建立整個樹結構。 –

+0

感謝您的更新答案。我已經創建了一個更復雜的關於上述的問題 - 你可以看一下嗎? - http://stackoverflow.com/questions/38984272/generating-xml-from-list-of-path-values – David542