David542 David542 - 3 months ago 9
Python Question

Write xml with a path and value

I have a list of paths and values, something like this:

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


And I want to build out the full xml structure, which would be:

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


Is there a way to do this with
lxml
? Or how could I build a function to fill in the inferred paths?

Answer

You could do something like:

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))

Which would give you:

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

You know Item is the root node and the first in every Path, so first create a tree using that node and then just add to the tree as you go.

Comments