Объединение XML-файлов, аналогичное поддержке нескольких файлов ConfigParser

#python #xml #configuration-files

#python #xml #конфигурация-файлы

Вопрос:

Я пишу модуль конфигурации приложения, который использует 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>
  

Это похоже на то, что делает ConfigParser Python с помощью своего метода read(), но выполняется с использованием XML. Как я могу это реализовать?

Ответ №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'}
  

Комментарии:

1. В конце концов, я пошел с JSON, но я также реализовал это при исследовании по этому вопросу. Создание собственных классов для представления конфигурации — самый чистый способ.

Ответ №2:

Обязательно ли использовать XML? То же самое можно было бы сделать с помощью JSON намного проще: предположим, что это текст из первого файла конфигурации:

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

и это текст из второго:

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

Затем, чтобы объединить to, вы просто загружаете каждый в 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. О JSON не может быть и речи, но я подумал, что XML будет удобен с XPaths и всем таким.