Получение библиотеки питонов ElementTree для сохранения пространств имен анализируемых файлов
Мне нужно манипулировать XML-файлами с помощью Python-Script для генерации тестовых данных для унаследованного приложения. Это значит, открыть файл, прочитать его, сделать некоторые манипуляции и записать в файл. Чтобы целевая система могла обрабатывать мои пространства имен тестовых данных, ДОЛЖНЫ быть сохранены в их первоначальной форме. Файлы, которые я обрабатываю, содержат строки вроде xmlns:EHC-1234="URI".
Поскольку библиотека elementTree обычно заменяет каждое пространство имен на новое, такое как ns0: ns1: и т. Д., Я придумала вот такую уродливую вещь:
#hack to preserve namespaces
for elem in ET.iterparse(xmlFile):
try:
try:
if elem[0][0] == "E":
ET.register_namespace(elem[0], elem[1])
except TypeError:
pass
except IndexError:
pass
tree = ET.parse(xmlFile)
#do stuff
.....
tree.write(filename, xml_declaration=True, encoding='utf-8', method="xml")
Это очевидно быстро и грязно. (Обратите внимание, что мне нужно проглотить все виды ошибок, потому что в файле, который я анализирую, есть много других тегов, а не только определений пространств имен. Я также должен дважды проанализировать мой файл, потому что пространства имен должны быть зарегистрированы перед анализом файла чтобы быть в силе при записи в файл снова.). Интересно, однако, как можно было бы сделать это хорошим способом? Есть ли у вас какие-либо идеи? Я пытался гуглить, но не нашел легкого решения, так что, возможно, где-то здесь есть "лучшая практика":)
Спасибо и ура Миша
1 ответ
Это может быть не лучшим способом сделать это, но я в основном делаю то же самое, анализируя только события "start-ns" (start Namespace), затем регистрирую пространство имен всякий раз, когда вижу один старт.
p_infile - это переменная, содержащая имя файла, который я собираюсь проанализировать.
"events" должен быть списком, но нам нужны только "start-ns".
events = "start-ns",
for event, elem in ET.iterparse(p_infile, events):
if event == "start-ns":
ET.register_namespace(elem[0], elem[1])
print("registered element " + str(elem))
Тест "if event == start-ns" явно избыточен, но если я захочу позже заняться другими событиями, такими как "start" или "end-ns", у меня есть структура. Так что без краткого изложения я бы понял:
events = "start-ns",
for event, elem in ET.iterparse(p_infile, events):
ET.register_namespace(elem[0], elem[1])
Я провел лишь ограниченное тестирование этого с XML-файлами с одним пространством имен, caveat emptor.