Получить родительский элемент после использования метода find (xml.etree.ElementTree)
Я работаю с огромным xml-файлом и пытаюсь извлечь информацию из разных элементов.
import xml.etree.ElementTree as ET
tree = ET.parse('t.xml')
root = tree.getroot()
Чтобы найти элементы, я использую метод find:
elm = root.find('.//Element[@elmid="1234"]')
Из этого я извлекаю информацию и, кроме того, мне нужна информация из родительского элемента. Но elm.find('..')
только возвращается None
как описано здесь: https://docs.python.org/3/library/xml.etree.elementtree.html
Теперь я использую следующие:
prt = root.find('.//Element[@elmid="1234"]/..')
elm = prt.find('/Element[@elmid="1234"]')
Это выглядит немного неестественно для меня, но работает.
Знаете ли вы лучший способ сделать это? Ты знаешь почему только None
возвращается?
1 ответ
xml.etree
API поддерживает только ограниченную версию XPath. xml.etree
документы для ..
Состояние выражения XPath:
Выбирает родительский элемент. Возвращает None, если путь пытается достичь предков начального элемента (был вызван поиск элемента).
Непосредственное получение родительского элемента не поддерживается в xml.etree
API. Поэтому я бы рекомендовал использовать lxml
где вы можете просто использовать getparent()
чтобы получить родительский элемент:
elm = root.find('.//Element[@elmid="1234"]')
elm.getparent()
lxml
также имеет полную реализацию XPath 1.0, поэтому elem.xpath('..')
будет работать так же.
У меня была похожая проблема, и я стал немного креативным. Оказывается, ничто не мешает нам самим добавлять информацию о происхождении. Позже мы можем лишить его, когда он нам больше не нужен.
def addParentInfo(et):
for child in et:
child.attrib['__my_parent__'] = et
addParentInfo(child)
def stripParentInfo(et):
for child in et:
child.attrib.pop('__my_parent__', 'None')
stripParentInfo(child)
def getParent(et):
if '__my_parent__' in et.attrib:
return et.attrib['__my_parent__']
else:
return None
tree = ...
addParentInfo(tree.getroot())
el = tree.findall(...)[0]
parent = getParent(el)
while parent:
...
parent = getParent(parent)
...
stripParentInfo(tree.getroot())