8

我正在尝试从 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()

conf_new.write('config-new.xml') 

有没有办法做到这一点,或者有人可以建议以不同的方式做到这一点?

4

8 回答 8

19

这会给你一个 dict 减属性。我不知道,这是否对任何人有用。当我想出这个时,我正在寻找一个 xml 来自己解决解决方案。


      
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

这个:http ://www.w3schools.com/XML/note.xml

<note>
 <to>Tove</to>
 <from>Jani</from>
 <heading>Reminder</heading>
 <body>Don't forget me this weekend!</body>
</note>

等于:


{'note': [{'to': 'Tove'},
          {'from': 'Jani'},
          {'heading': 'Reminder'},
          {'body': "Don't forget me this weekend!"}]}
于 2010-02-20T21:07:56.783 回答
11

我不确定首先将信息集转换为嵌套字典是否更容易。使用 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 树转换为列表和属性,因为它在内部完全使用它。

它还支持XPath的小子集。

于 2008-09-24T14:58:52.437 回答
8

为了在 python 中轻松操作 XML,我喜欢Beautiful Soup库。它的工作原理是这样的:

示例 XML 文件:

<root>
  <level1>leaf1</level1>
  <level2>leaf2</level2>
</root>

Python代码:

from BeautifulSoup import BeautifulStoneSoup, Tag, NavigableString

soup = BeautifulStoneSoup('config-template.xml') # get the parser for the xml file
soup.contents[0].name
# u'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>
于 2008-09-24T15:56:06.323 回答
4

我修改了丹尼尔的答案,以提供一个稍微整洁的字典:

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 是 xmlns 字符串,包括大括号,ElementTree 将它添加到所有标签之前,所以在这里我已经清除了它,因为整个文档都有一个命名空间

请注意,我也调整了原始 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!"}}

它是为特定的xml设计的,基本上相当于json,应该处理元素属性,例如

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

有可能合并属性字典/子标签字典,类似于如何合并重复子标签,尽管嵌套列表似乎有点合适:-)

于 2011-05-22T13:06:04.733 回答
1

添加这一行

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

user247686 的代码中,您也可以拥有节点属性。

在这篇文章中找到它https://stackoverflow.com/a/7684581/1395962

例子:

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)
于 2012-05-15T11:37:03.080 回答
0

你试过这个吗?

print xml.etree.ElementTree.tostring( conf_new )
于 2008-09-24T15:05:01.500 回答
0

对我最直接的方式:

root        = ET.parse(xh)
data        = root.getroot()
xdic        = {}
if data > None:
    for part in data.getchildren():
        xdic[part.tag] = part.text
于 2010-03-30T12:57:33.753 回答
0

XML 具有丰富的信息集,它需要一些特殊的技巧才能在 Python 字典中表示它。元素是有序的,属性与元素主体区分开来,等等。

一个处理 XML 和 Python 字典之间往返的项目,以及一些用于以不同方式处理权衡的配置选项是Pickling Tools 中的 XML 支持。需要 1.3 和更新版本。它不是纯 Python(实际上旨在使 C++/Python 交互更容易),但它可能适用于各种用例。

于 2012-03-22T01:31:08.193 回答