2016-08-16 25 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