так как у меня была эта неприятная проблема во второй раз, я подумал, что просьба поможет.
Иногда мне приходится получать элементы из XML-документов, но способы сделать это неудобны.
Мне нравится знать библиотеку python, которая делает то, что я хочу, элегантный способ сформулировать мои XPaths, способ автоматически регистрировать пространства имен в префиксах или скрытые предпочтения во встроенных реализациях XML или в lxml для полного заполнения пространств имен. Уточнение следует, если вы уже не знаете, чего я хочу:)
Пример-документ:
<root xmlns="http://really-long-namespace.uri"
xmlns:other="http://with-ambivalent.end/#">
<other:elem/>
</root>
Что я могу сделать
API ElementTree является единственным встроенным (я знаю), предоставляющим запросы XPath. Но это требует от меня использовать "имена". Это выглядит так: /{http://really-long-namespace.uri}root/{http://with-ambivalent.end/#}elem
Как вы можете видеть, они довольно многословны. Я могу сократить их, выполнив следующие действия:
default_ns = "http://really-long-namespace.uri"
other_ns = "http://with-ambivalent.end/#"
doc.find("/{{{0}}}root/{{{1}}}elem".format(default_ns, other_ns))
Но это как {{{уродливый}}} и хрупкий, так как http…end/#
≃ http…end#
≃ http…end/
≃ http…end
, и кто я должен знать, какой вариант будет использоваться?
Кроме того, lxml поддерживает префиксы пространства имен, но он не использует те, которые содержатся в документе, и не обеспечивает автоматизированный способ работы с пространствами имен по умолчанию. Я все равно должен получить один элемент каждого пространства имен, чтобы извлечь его из документа. Атрибуты пространства имен не сохраняются, поэтому нет возможности автоматически извлекать их из них.
Существует также пространственный алгоритм запросов XPath, но он также является подробным/уродливым и недоступным во встроенной реализации: /*[local-name() = 'root']/*[local-name() = 'elem']
Что я хочу сделать
Я хочу найти библиотеку, опцию или общую функцию XPath-morphing для достижения вышеприведенных примеров, набрав немного больше, чем следующее...
- Unnamespaced:
/root/elem
- Префикс пространства имен из документа:
/root/other:elem
... плюс, возможно, некоторые утверждения, которые я действительно хочу использовать префиксы документов или разделять пространства имен.
Дальнейшие разъяснения: хотя мой нынешний вариант использования так же прост, мне придется использовать более сложные в будущем.
Спасибо за чтение!
решаемые
Пользователь samplebias обратил мое внимание на py-dom-xpath; Именно то, что я искал. Теперь мой фактический код выглядит следующим образом:
#parse the document into a DOM tree
rdf_tree = xml.dom.minidom.parse("install.rdf")
#read the default namespace and prefix from the root node
context = xpath.XPathContext(rdf_tree)
name = context.findvalue("//em:id", rdf_tree)
version = context.findvalue("//em:version", rdf_tree)
#<Description/> inherits the default RDF namespace
resource_nodes = context.find("//Description/following-sibling::*", rdf_tree)
В соответствии с документом, простым, с поддержкой пространства имен; совершенны.