合并XML文件类似于ConfigParser的多文件支持

2 投票
2 回答
834 浏览
提问于 2025-04-17 03:51

我正在写一个应用程序配置模块,它的文件使用XML格式。我们来看一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<Settings>
    <PathA>/Some/path/to/directory</PathA>
    <PathB>/Another/path</PathB>
</Settings>

现在,我想在一个后面加载的不同文件中覆盖某些元素。下面是覆盖文件的例子:

<?xml version="1.0" encoding="UTF-8"?>
<Settings>
    <PathB>/Change/this/path</PathB>
</Settings>

当我用XPath查询这个包含覆盖内容的文档时,我希望得到这样的元素树:

<?xml version="1.0" encoding="UTF-8"?>
<Settings>
    <PathA>/Some/path/to/directory</PathA>
    <PathB>/Change/this/path</PathB>
</Settings>

这和Python的ConfigParser用它的read()方法的做法类似,不过是用XML来实现的。我该怎么做呢?

2 个回答

0

你真的必须使用XML吗?其实用JSON可以更简单地实现同样的功能:

假设这是第一个配置文件的内容:

text='''
{
  "PathB": "/Another/path", 
  "PathA": "/Some/path/to/directory"
}
'''

这是第二个配置文件的内容:

text2='''{
  "PathB": "/Change/this/path"
}'''

然后要把这两个合并,你只需要把它们分别加载到一个dict(字典)里,然后调用update方法:

import json
config=json.loads(text)
config2=json.loads(text2)
config.update(config2)
print(config)

这样就得到了Python的dict

{u'PathB': u'/Change/this/path', u'PathA': u'/Some/path/to/directory'}
1

你可以把XML转换成一个Python类的实例:

import lxml.etree as ET
import io

class Settings(object):
    def __init__(self,text):
        root=ET.parse(io.BytesIO(text)).getroot()
        self.settings=dict((elt.tag,elt.text) for elt in root.xpath('/Settings/*'))
    def update(self,other):
        self.settings.update(other.settings)

text='''\
<?xml version="1.0" encoding="UTF-8"?>
<Settings>
    <PathA>/Some/path/to/directory</PathA>
    <PathB>/Another/path</PathB>
</Settings>'''

text2='''\
<?xml version="1.0" encoding="UTF-8"?>
<Settings>
    <PathB>/Change/this/path</PathB>
</Settings>'''    

s=Settings(text)
s2=Settings(text2)
s.update(s2)
print(s.settings)

这样就能得到

{'PathB': '/Change/this/path', 'PathA': '/Some/path/to/directory'}

撰写回答