2016-02-23 1 views
2

У меня есть файл ввода XML:Как заставить ElementTree сохранить атрибут xmlns в его исходном элементе?

<?xml version='1.0' encoding='utf-8'?> 
<configuration> 
    <runtime name="test" version="1.2" xmlns:ns0="urn:schemas-microsoft-com:asm.v1"> 
    <ns0:assemblyBinding> 
     <ns0:dependentAssembly /> 
    </ns0:assemblyBinding> 
    </runtime> 
</configuration> 

... и скрипт на Python:

import xml.etree.ElementTree as ET 

file_xml = 'test.xml' 

tree = ET.parse(file_xml) 
root = tree.getroot() 
print (root.tag) 
print (root.attrib) 

element_runtime = root.find('.//runtime') 
print (element_runtime.tag) 
print (element_runtime.attrib) 

tree.write(file_xml, xml_declaration=True, encoding='utf-8', method="xml") 

... который дает следующий результат:

>test.py 
configuration 
{} 
runtime 
{'name': 'test', 'version': '1.2'} 

... и имеет нежелательный побочный эффект модификации XML:

<?xml version='1.0' encoding='utf-8'?> 
<configuration xmlns:ns0="urn:schemas-microsoft-com:asm.v1"> 
    <runtime name="test" version="1.2"> 
    <ns0:assemblyBinding> 
     <ns0:dependentAssembly /> 
    </ns0:assemblyBinding> 
    </runtime> 
</configuration> 

Мой оригинальный скрипт изменяет XML, поэтому мне нужно позвонить tree.write и сохранить отредактированный файл. Но проблема в том, что парсер ElementTree перемещает атрибут xmlns от элемента runtime до корневого элемента configuration, что нежелательно в моем случае.

Я не могу удалить атрибут xmlns из корневого элемента (удалить его из словаря его атрибутов), поскольку он не указан в списке его атрибутов (в отличие от атрибутов, перечисленных для элемента runtime).

Почему атрибут xmlns никогда не попадает в список атрибутов для любого элемента?

Как заставить ElementTree сохранить атрибут xmlns в его исходном элементе?

Я использую Python 3.5.1 для Windows.

+1

'etree' [тянет все пространства имен в первый элемент] (https://hg.python.org/cpython/file/v3.5.0/Lib/xml/etree/ElementTree.py#l771), поскольку он внутренне не работает 't отслеживать, на каком элементе пространство имен было объявлено первоначально. Если вы этого не хотите, вам придется писать собственную логику сериализации или вместо этого использовать lxml. Но не должно иметь никакого значения, где объявляется пространство имен. – mata

+0

Я использую Python для изменения конфигурационного файла .NET app, который не должен содержать декларации пространства имен в корневом элементе (http://blogs.msdn.com/b/junfeng/archive/2008/03/24/app-config-s -root-элемент-должна-быть-имена-less.aspx). –

+0

Что? WTF - это mircrosoft, использующий для разбора xml ??? Думаю, тогда ваш лучший выбор будет заключаться в использовании ['lxml'] (http://lxml.de/) вместо' xml.etree', поскольку он, по-видимому, уважает позиционирование объявлений namsepace. – mata

ответ

2

xml.etree.ElementTree переносит все пространства имен в первый элемент, поскольку он внутренне не отслеживает, на каком элементе пространство имен было объявлено первоначально.

Если вы этого не хотите, вам придется написать собственную логику сериализации.

Лучшей альтернативой могло бы быть использование lxml вместо xml.etree, поскольку оно сохраняет место, где объявлен префикс пространства имен.

 Смежные вопросы

  • Нет связанных вопросов^_^