Я хочу использовать метод «findall», чтобы найти некоторые элементы исходного файла xml в модуле ElementTree.
Однако исходный xml-файл (test.xml) имеет пространство имен. Я обрезаю часть xml файла как образец:
<?xml version="1.0" encoding="iso-8859-1"?>
<XML_HEADER xmlns="http://www.test.com">
<TYPE>Updates</TYPE>
<DATE>9/26/2012 10:30:34 AM</DATE>
<COPYRIGHT_NOTICE>All Rights Reserved.</COPYRIGHT_NOTICE>
<LICENSE>newlicense.htm</LICENSE>
<DEAL_LEVEL>
<PAID_OFF>N</PAID_OFF>
</DEAL_LEVEL>
</XML_HEADER>
Пример кода Python ниже:
from xml.etree import ElementTree as ET
tree = ET.parse(r"test.xml")
el1 = tree.findall("DEAL_LEVEL/PAID_OFF") # Return None
el2 = tree.findall("{http://www.test.com}DEAL_LEVEL/{http://www.test.com}PAID_OFF") # Return <Element '{http://www.test.com}DEAL_LEVEL/PAID_OFF' at 0xb78b90>
Хотя это может работать, поскольку существует пространство имен "{http://www.test.com}", очень неудобно добавлять пространство имен перед каждым тегом.
Как я могу игнорировать пространство имен при использовании методов «find», «findall» и так далее?
python
namespaces
find
elementtree
findall
KevinLeng
источник
источник
tree.findall("xmlns:DEAL_LEVEL/xmlns:PAID_OFF", namespaces={'xmlns': 'http://www.test.com'})
достаточно удобно?tree.findall("{0}DEAL_LEVEL/{0}PAID_OFF".format('{http://www.test.com}'))
Ответы:
Вместо изменения самого XML-документа лучше всего проанализировать его, а затем изменить теги в результате. Таким образом, вы можете обрабатывать несколько пространств имен и псевдонимов пространства имен:
Это основано на обсуждении здесь: http://bugs.python.org/issue18304
Обновление:
rpartition
вместо того,partition
чтобы убедиться, что вы получите имя тега,postfix
даже если нет пространства имен. Таким образом, вы можете сжать это:источник
et.findall('{*}sometag')
. И это также искажает само дерево элементов, а не просто «выполняет поиск, игнорируя пространства имен только в этот раз, без повторного анализа документа и т. Д., Сохраняя информацию о пространстве имен». Что ж, в этом случае вам необходимо пройти по дереву и убедиться, что узел соответствует вашим пожеланиям после удаления пространства имен.Если вы удалите атрибут xmlns из xml перед его анализом, то к каждому тегу в дереве не будет добавлено пространство имен.
источник
=
знака равенства.Ответы до сих пор явно помещают значение пространства имен в сценарий. Для более общего решения я бы предпочел извлечь пространство имен из xml:
И используйте его в методе поиска:
источник
namespace
Вот расширение ответа nonagon, которое также удаляет пространства имен из атрибутов:
ОБНОВЛЕНИЕ: добавлено,
list()
чтобы итератор работал (необходимо для Python 3)источник
Улучшение ответа от ericspod:
Вместо глобального изменения режима разбора мы можем обернуть это в объект, поддерживающий конструкцию with.
Это может быть использовано следующим образом
Прелесть этого способа в том, что он не меняет никакого поведения для несвязанного кода вне блока with. Я закончил тем, что создал это после получения ошибок в несвязанных библиотеках после использования версии ericspod, которая также использовала expat.
источник
xml.etree.ElementTree.XMLParser
каким-то образом оптимизирован, а патчирование обезьян неexpat
имеет абсолютно никакого эффекта.Вы также можете использовать элегантную конструкцию форматирования строки:
или, если вы уверены, что PAID_OFF появляется только на одном уровне дерева:
источник
Если вы используете,
ElementTree
но неcElementTree
можете заставить Expat игнорировать обработку пространства имен, заменивParserCreate()
:ElementTree
пытается использовать Expat, вызывая,ParserCreate()
но не предоставляет возможности не предоставлять строку разделителя пространства имен, приведенный выше код приведет к его игнорированию, но предупреждаем, что это может нарушить другие вещи.источник
ElementTree.fromstring(s, parser=None)
я пытаюсь передать ему парсер.Возможно, я опоздаю, но не думаю, что
re.sub
это хорошее решение.Однако перезапись
xml.parsers.expat
не работает для версий Python 3.x,Главный виновник -
xml/etree/ElementTree.py
нижняя часть исходного кода.Что довольно грустно.
Решение состоит в том, чтобы сначала избавиться от него.
Проверено на Python 3.6.
try
Оператор try полезен в случае, если где-то в вашем коде вы дважды перезагружаете или импортируете модуль, вы получаете странные ошибки, напримеркстати, черт побери, исходный код etree выглядит действительно беспорядочно.
источник
Давайте объединим ответ девятиугольника в с ответом mzjn к связанному с этим вопрос :
Используя эту функцию мы:
Создайте итератор, чтобы получить как пространства имен, так и проанализированный объект дерева .
Итерация над созданным итератором , чтобы получить пространство имен Сыроватские , что мы можем позже передать в каждом
find()
илиfindall()
вызове в качестве мотивационных по iMom0 .Я думаю, что это лучший подход, так как здесь нет никаких манипуляций ни с исходным XML, ни с полученным в результате проанализированным
xml.etree.ElementTree
выводом.Я также хотел бы отметить ответ Барни, предоставив важную часть этой головоломки (которую вы можете получить проанализированный корень у итератора). До этого я фактически дважды просматривал дерево XML в своем приложении (один раз, чтобы получить пространства имен, второй - для корня).
источник
find()
иfindall()
. Вы просто кормите эти методы диктовкой пространства именparse_xml()
и используете префикс пространства имен в своих запросах. Например:et_element.findall(".//some_ns_prefix:some_xml_tag", namespaces=xml_namespaces)