用路径和值写入 xml
Write xml with a path and value
我有一个路径和值列表,如下所示:
[
{'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
做到这一点?或者我如何构建一个函数来填充推断的路径?
是的,您可以使用 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']
注意:而不是"Path",我更喜欢"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>
当然有限制。
你可以这样做:
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
是根节点,也是每个路径中的第一个节点,所以首先使用该节点创建一个树,然后在你去的时候添加到树中。
我有一个路径和值列表,如下所示:
[
{'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
做到这一点?或者我如何构建一个函数来填充推断的路径?
是的,您可以使用 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']
注意:而不是"Path",我更喜欢"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>
当然有限制。
你可以这样做:
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
是根节点,也是每个路径中的第一个节点,所以首先使用该节点创建一个树,然后在你去的时候添加到树中。