#python #xml #lxml
#python #xml #lxml
Вопрос:
С учетом lxml.etree возможно ли каким-либо образом создать объектное представление дерева, чтобы к вложенным элементам можно было обращаться объектно-подобным образом (с помощью оператора ‘.’)?
Я знаю, что в lxml есть библиотека под названием objectify, но, похоже, ее можно создать только с учетом необработанного XML, а для добавления новых элементов в дерево все еще требуется пройти через создание узла, подобного etree.
В идеале то, чего я хочу достичь, это:
tree = objectify( etree_root )
print tree.somenode.get( 'attrib_name' )
tree.somenode.set( 'attrib_name', 'some_val' )
Node( tree.somenode, "somechild" )
tree.somenode.somechild.set( 'attrib', 'foo' )
Ответ №1:
Я думаю, вам нужно переопределить __setattribute__
соответственно __getattribute__
операторы. Я думаю, вам нужно создать подкласс etree.Класс элемента для достижения этого.
Но, с другой стороны, этот API также был бы довольно непрактичным, поскольку могло бы быть несколько дочерних узлов с одинаковым именем тега.
Для поиска элементов вы также можете использовать выражения XPath, которые соответствуют вашей идее. API выглядит следующим образом:
subchild = root.find('child/subchild')
Комментарии:
1. Не совсем непрактично. С помощью некоторых разумных изменений вы можете сделать его полезным для некоторых типов данных. Вы можете переопределить
__get_attribute__
таким образом, что еслиnode.childname
на него ссылаются, он будет возвращать только к первому дочернему элементу, но для `node.childnames (с ‘s’ в конце) он вернет их список. Действительно ли этот дизайн полезен или нет, зависит от ваших XML-данных.2. Спасибо за совет. На самом деле это проще, чем я думал. Мне удалось объективизировать каждый элемент в довольно большом XML-дереве (~ 20 мс). Это позволяет делать такие вещи, как:
root.child.nonexistentchild[ "attrib" ] = "hello"
Это создаетnonexistentchild
на лету и добавляет атрибутattrib
со значениемhello
. Требуется просто переопределение__setattr__
,__getattr__
,__get__
__set__
. Затем вы просто создаете объективированное дерево, беря каждый узел и создавая объектную оболочку для каждого родственного элемента.3. аккуратно 🙂 случайно, нельзя ли откуда-нибудь взять код?
4. Нет, боюсь, по юридическим причинам я не могу этого сделать. Одна вещь, с которой следует быть осторожным, — это последовательности. Поскольку при объективизации вы не утверждаете в схеме XSD, если в исходном XML-дереве есть один элемент, у вас нет способа узнать, является ли он частью последовательности или нет. Вы можете обойти это, предоставив метод для «преобразования» в последовательность, если требуется.