在python中将XML编辑为字典?

在python中将XML编辑为字典?,python,xml,dictionary,Python,Xml,Dictionary,我试图从python中的模板xml文件生成定制的xml文件 从概念上讲,我希望读入模板xml,删除一些元素,更改一些文本属性,并将新的xml写入文件。我希望它能像这样工作: conf_base = ConvertXmlToDict('config-template.xml') conf_base_dict = conf_base.UnWrap() del conf_base_dict['root-name']['level1-name']['leaf1'] del conf_base_dict[

我试图从python中的模板xml文件生成定制的xml文件

从概念上讲,我希望读入模板xml,删除一些元素,更改一些文本属性,并将新的xml写入文件。我希望它能像这样工作:

conf_base = ConvertXmlToDict('config-template.xml')
conf_base_dict = conf_base.UnWrap()
del conf_base_dict['root-name']['level1-name']['leaf1']
del conf_base_dict['root-name']['level1-name']['leaf2']

conf_new = ConvertDictToXml(conf_base_dict)
现在我想写文件,但我不知道怎么写 ElementTree.ElementTree.write()


有什么方法可以做到这一点,或者有人可以建议用另一种方法做到这一点吗

我不确定首先将信息集转换为嵌套dict是否更容易。使用ElementTree,可以执行以下操作:

import xml.etree.ElementTree as ET
doc = ET.parse("template.xml")
lvl1 = doc.findall("level1-name")[0]
lvl1.remove(lvl1.find("leaf1")
lvl1.remove(lvl1.find("leaf2")
# or use del lvl1[idx]
doc.write("config-new.xml")
ElementTree的设计使您不必首先将XML树转换为列表和属性,因为它在内部正是这样使用的

它还支持作为的小子集。

您尝试过这个吗

print xml.etree.ElementTree.tostring( conf_new )

为了在python中轻松操作XML,我喜欢这个库。它的工作原理如下:

conf_base = ConvertXmlToDict('config-template.xml')
conf_base_dict = conf_base.UnWrap()
del conf_base_dict['root-name']['level1-name']['leaf1']
del conf_base_dict['root-name']['level1-name']['leaf2']

conf_new = ConvertDictToXml(conf_base_dict)
示例XML文件:

<root>
  <level1>leaf1</level1>
  <level2>leaf2</level2>
</root>
可以将节点名称用作方法:

soup.root.contents[0].name
# u'level1'
也可以使用正则表达式:

import re
tags_starting_with_level = soup.findAll(re.compile('^level'))
for tag in tags_starting_with_level: print tag.name
# level1
# level2
添加和插入新节点非常简单:

# build and insert a new level with a new leaf
level3 = Tag(soup, 'level3')
level3.insert(0, NavigableString('leaf3')
soup.root.insert(2, level3)

print soup.prettify()
# <root>
#  <level1>
#   leaf1
#  </level1>
#  <level2>
#   leaf2
#  </level2>
#  <level3>
#   leaf3
#  </level3>
# </root>
#构建并插入带有新叶的新关卡
level3=标签(汤“level3”)
级别3.插入(0,NavigableString('leaf3'))
汤。根。插入(2,3级)
打印汤。美化
# 
#  
#叶1
#  
#  
#叶子2
#  
#  
#叶3
#  
# 

这将为您提供一个dict减去属性的解决方案。我不知道,这是否对任何人都有用。当我提出这个方案时,我自己正在寻找一个xml到dict的解决方案


      
import xml.etree.ElementTree as etree

tree = etree.parse('test.xml')
root = tree.getroot()

def xml_to_dict(el):
  d={}
  if el.text:
    d[el.tag] = el.text
  else:
    d[el.tag] = {}
  children = el.getchildren()
  if children:
    d[el.tag] = map(xml_to_dict, children)
  return d
这:


对我来说最直接的方式是:

root        = ET.parse(xh)
data        = root.getroot()
xdic        = {}
if data > None:
    for part in data.getchildren():
        xdic[part.tag] = part.text

我修改了丹尼尔的答案,使之成为一本稍微整洁的词典:

def xml_to_dictionary(element):
    l = len(namespace)
    dictionary={}
    tag = element.tag[l:]
    if element.text:
        if (element.text == ' '):
            dictionary[tag] = {}
        else:
            dictionary[tag] = element.text
    children = element.getchildren()
    if children:
        subdictionary = {}
        for child in children:
            for k,v in xml_to_dictionary(child).items():
                if k in subdictionary:
                    if ( isinstance(subdictionary[k], list)):
                        subdictionary[k].append(v)
                    else:
                        subdictionary[k] = [subdictionary[k], v]
                else:
                    subdictionary[k] = v
        if (dictionary[tag] == {}):
            dictionary[tag] = subdictionary
        else:
            dictionary[tag] = [dictionary[tag], subdictionary]
    if element.attrib:
        attribs = {}
        for k,v in element.attrib.items():
            attribs[k] = v
        if (dictionary[tag] == {}):
            dictionary[tag] = attribs
        else:
            dictionary[tag] = [dictionary[tag], attribs]
    return dictionary
namespace是ElementTree在所有标记前面加上的xmlns字符串,包括大括号,所以在这里我清除了它,因为整个文档只有一个名称空间

注意,我也调整了原始xml,以便“空”标记在ElementTree表示中最多生成一个“”文本属性

spacepattern = re.compile(r'\s+')
mydictionary = xml_to_dictionary(ElementTree.XML(spacepattern.sub(' ', content)))
例如,我会给

{'note': {'to': 'Tove',
         'from': 'Jani',
         'heading': 'Reminder',
         'body': "Don't forget me this weekend!"}}
它是为基本上等同于json的特定xml设计的,应该处理元素属性,例如

<elementName attributeName='attributeContent'>elementContent</elementName>
elementContent


可以像合并重复子标记一样合并属性字典/子标记字典,尽管嵌套列表似乎有点合适:-)

XML有丰富的信息集,在Python字典中表示这一点需要一些特殊技巧。元素是有序的,属性与元素体是不同的,等等

处理XML和Python字典之间往返的一个项目是。需要1.3版及更高版本。它不是纯Python(实际上是为了使C++和Python交互更容易),但是它可能适合于各种用例。

< P>添加这行< /P>
d.update(('@' + k, v) for k, v in el.attrib.iteritems())
在中,也可以具有节点属性

在这个帖子里找到的

示例:

import xml.etree.ElementTree as etree
from urllib import urlopen

xml_file = "http://your_xml_url"
tree = etree.parse(urlopen(xml_file))
root = tree.getroot()

def xml_to_dict(el):
    d={}
    if el.text:
        d[el.tag] = el.text
    else:
        d[el.tag] = {}
    children = el.getchildren()
    if children:
        d[el.tag] = map(xml_to_dict, children)

    d.update(('@' + k, v) for k, v in el.attrib.iteritems())

    return d
称为

xml_to_dict(root)

BeautifulSoup将所有内容转换为小写。那真糟糕。我必须保留标签和值的案例!BeautifulSoup的作者说它之所以这样做是因为HTMLPasser做到了这一点。“如果您需要保留标记大小写,请尝试lxml”。最好在
lvl1
赋值中使用
find
,而不是
findall
并获取第一个元素。这正是我要寻找的。使用
map
可以为我获得额外积分。做得好。
d.update(('@' + k, v) for k, v in el.attrib.iteritems())
import xml.etree.ElementTree as etree
from urllib import urlopen

xml_file = "http://your_xml_url"
tree = etree.parse(urlopen(xml_file))
root = tree.getroot()

def xml_to_dict(el):
    d={}
    if el.text:
        d[el.tag] = el.text
    else:
        d[el.tag] = {}
    children = el.getchildren()
    if children:
        d[el.tag] = map(xml_to_dict, children)

    d.update(('@' + k, v) for k, v in el.attrib.iteritems())

    return d
xml_to_dict(root)