9. Класс Element: один элемент дерева¶
Каждый элемент XML представлен экземпляром класса Element.
- См. Раздел 9.1. Атрибуты экземпляра элемента для атрибутов экземпляра элемента в смысле Python, в отличие от атрибутов XML.
- См. Раздел 9.2. Доступ к списку дочерних элементов для различных способов доступа к элементам дочерних элементов элемента.
- Различные методы экземпляров Element следуют в алфавитном порядке, начиная с раздела 9.3. Element.append(): добавить новый дочерний элемент.
9.1. Атрибуты экземпляра элемента¶
Каждый экземпляр класса Element имеет эти атрибуты.
- .attrib
- Словарь, содержащий атрибуты элемента. Ключами являются имена атрибутов, и каждое соответствующее значение является значением атрибута.
- .base
- Базовый URI из атрибута xml: base, который этот элемент содержит или наследует, если таковой имеется. В противном случае None.
- .prefix
- Префикс пространства имен этого элемента, если он есть, в противном случае None.
- .sourceline
- Номер строки этого элемента при анализе, если известен, в противном случае Нет.
- .tag
- Имя элемента.
- .tail
- Текст, следующий за закрывающим тегом этого элемента, вплоть до начального тега следующего элемента sibling. Если там не было текста, этот атрибут будет иметь значение None.
Этот способ связывания текста с элементами не является типичным для большинства моделей обработки XML; см. раздел 2 «Как ElementTree представляет XML».
- .text
- Текст внутри элемента, вплоть до начального тега первого дочернего элемента. Если там не было текста, этот атрибут будет иметь значение None.
9.2. Доступ к списку дочерних элементов¶
Во многих случаях экземпляр Element действует как список Python, а его дочерние элементы XML действуют как члены этого списка.
Вы можете использовать функцию len() Python, чтобы определить, сколько детей имеет элемент. Например, если узел является экземпляром Element с пятью дочерними элементами элемента, len(node) вернет значение 5.
Вы можете добавлять, заменять или удалять дочерние элементы элемента, используя регулярные операции с списком Python. Например, если узел экземпляра Element имеет три дочерних элемента, узел [0] является первым потомком, а узел [2] является третьим.
В следующих примерах предположим, что E является экземпляром элемента.
- E [i] возвращает дочерний элемент E в позиции i, если он есть. Если в этой позиции нет дочернего элемента, эта операция вызывает исключение IndexError.
E [i: j] возвращает список дочерних элементов между позициями i и j.
Например, node[2: 4] возвращает список, содержащий третий и четвертый дочерние узлы узла.
- Вы можете заменить один дочерний элемент E новым элементом c, используя инструкцию этого вида:
E[i] = c
Если i не является существующим дочерним элементом, эта операция вызовет исключение IndexError.
- Вы можете заменить последовательность соседних дочерних элементов элемента E, используя назначение среза:
E[i:j] = seq
где seq - последовательность экземпляров Element.
Если срез [i:j] не указывает существующий набор дочерних элементов, эта операция вызывает исключение IndexError.
- Вы можете удалить один из таких элементов:
del E[i]
где i - индекс этого ребенка.
- Вы можете удалить фрагмент из списка дочерних элементов элемента следующим образом:
del E[i:j]
- Вы можете перебирать дочерние элементы элемента с циклом for. Например, если узел является экземпляром элемента, этот код будет печатать теги всех его дочерних элементов:
for kid in node:
print kid.tag
Не все дети элемента сами по себе являются элементами.
- Инструкции по обработке - это примеры класса
etree._ProcessingInstruction.
- Комментарии - это примеры класса
etree._Comment.
Если вам нужно проверить, является ли данный дочерний узел инструкцией обработки или комментарием, вы можете использовать встроенную функцию Python isinstance(I, C), которая проверяет, является ли объект I экземпляром класса или подкласса класса C.
Например, чтобы проверить, является ли узел комментарием, вы можете использовать этот тест, который возвращает True, если узел является комментарием, False в противном случае.
issubclass(node, etree._Comment)
9.3. Element.append(): добавить новый дочерний элемент¶
Чтобы добавить нового элемента c в элемент E, используйте этот метод:
E.append(c)
Вы можете использовать этот метод для добавления экземпляров Comment и ProcessingInstruction в качестве дочерних элементов элемента, а также экземпляров Element.
Вот пример:
>>> st = etree.Element("state", name="New Mexico")
>>> etree.tostring(st)
'<state name="New Mexico"/>'
>>> co = etree.Element("county", name="Socorro")
>>> st.append(co)
>>> etree.tostring(st)
'<state name="New Mexico"><county name="Socorro"/></state>'
>>> rem = etree.Comment("Just another day in paradise.")
>>> st.append(rem)
>>> etree.tostring(st)
'<state name="New Mexico"><county name="Socorro"/><!-- Just another day in
paradise. --></state>'
>>>
9.4. Element.clear(): Сделать элемент пустым¶
Вызов метода .clear() на экземпляре Element удаляет все его содержимое:
- Все значения удаляются из словаря .attrib.
- У атрибутов .text и .tail устанавливаются значение None.
- Любые дочерние элементы удаляются.
9.5. Element.find(): найдите соответствующий подэлемент¶
Вы можете искать подэлементы экземпляра Element E , используя этот метод:
E.find(path[, namespaces=D])
Этот метод выполняет поиск элемента и его потомков для одного элемента, который соответствует шаблону, описываемому аргументом path.
- Если имеется ровно один соответствующий элемент, этот метод возвращает этот элемент как экземпляр элемента.
- Если имеется несколько совпадающих элементов, метод возвращает тот, который появляется первым в порядке документа.
- Если нет соответствующих элементов, он возвращает None.
Аргумент path - это строка, описывающая элемент, для которого вы ищете. Возможные значения:
- “tag”
- Найдите первый дочерний элемент, чье имя является «tag».
“tag1/tag2/.../tagn”
Найдите первый дочерний элемент, чье имя - tag1; затем под этим дочерним элементом найдите первый дочерний элемент с именем tag2; и так далее.
Например, если узел является экземпляром Element, у которого есть дочерний элемент с тегом «county», и этот ребенок, в свою очередь, имеет дочерний элемент с тегом «seat», это выражение вернет элемент, соответствующий элементу «seat»:
node.find("county/seat")
Необязательный аргумент namespaces - это карта пространства имен; см. раздел 4.3 «Карты пространства имен». Если он указан, эта карта используется для интерпретации префиксов пространства имен в аргументе path.
Например, предположим, что у вас есть элемент someNode, и вы хотите найти дочерний элемент с именем roundtable в пространстве имен с именем http://example.com/mphg/, и под ним вы хотите найти дочерний элемент с именем knight в пространстве имен с именем http://example.org/sirs/ns/. Это сделает вызов :
nsd = {'mp': 'http://example.com/mphg/',
'k': 'http://example.org/sirs/ns/'}
someNode.find('mp:roundtable/k:knight', namespaces=nsd}
Обратите внимание, что префиксы пространства имен, которые вы определяете таким образом, не должны иметь какого-либо определенного значения или соответствовать префиксам пространства имен, которые могут использоваться для этих NSURI в внешней форме документа.
Предупреждение
Аргумент ключевого слова namespaces для метода .find() доступен только для версии 2.3.0 или более поздней версии etree.
9.6. Element.findall(): найти все соответствующие подэлементы¶
Этот метод возвращает список потомков элемента, который соответствует шаблону, описываемому аргументом path.
E.findall(path[, namespaces=N])
Способ, которым аргумент пути описывает желаемый набор узлов, работает так же, как аргумент пути, описанный в разделе 9.5. Element.find(): найдите соответствующий подэлемент.
Например, если элемент статьи с именем root имеет ноль или более детей с именем section, этот вызов будет формировать список sectionList, содержащий экземпляры Element, представляющие этих детей.
sectionList = root.findall('section')
Необязательный аргумент ключевого слова namespaces позволяет указать карту пространства имен. Если указано, эта карта пространства имен используется для интерпретации префиксов пространства имен в пути; в разделе 9.5. Element.find(): найдите соответствующий подэлемент для получения более подробной информации.
Предупреждение
Аргумент ключевого слова namespaces доступен только с версии 2.3.0 версии lxml.etree.
9.7. Element.findtext(): извлечение текстового содержимого¶
Чтобы найти текстовое содержимое внутри определенного элемента, вызовите этот метод, где E является некоторым предком этого элемента:
E.findtext(path, default=None, namespaces=N)
Аргумент path указывает желаемый элемент таким же образом, как и аргумент path в разделе 9.5. Element.find(): найдите соответствующий подэлемент.
- Если существуют какие-либо потомки E, которые соответствуют данному пути, этот метод возвращает текстовое содержимое первого элемента соответствия.
- Если есть хотя бы один соответствующий элемент, но он не имеет текстового содержимого, возвращаемое значение будет пустой строкой.
- Если никакие элементы не соответствуют указанному пути, метод возвращает None или значение аргумента ключевого слова default =, если вы его предоставили.
Вот пример.
>>> from lxml import etree
>>> node=etree.fromstring('<a><b>bum</b><b>ear</b><c/></a>')
>>> node.findtext('b')
'bum'
>>> node.findtext('c')
''
>>> node.findtext('c', default='Huh?')
''
>>> print node.findtext('x')
None
>>> node.findtext('x', default='Huh?')
'Huh?'
Необязательный аргумент ключевого слова namespaces позволяет указать префиксы пространства имен для документов с несколькими именами; для получения дополнительной информации см. раздел 9.5. Element.find(): найдите соответствующий подэлемент.
9.8. Element.get(): получить значение атрибута с дефолтным значением¶
Существует два способа получить значение атрибута из экземпляра элемента. См. Также словарь .attrib в разделе 9.1. Атрибуты экземпляра элемента.
Метод .get() в экземпляре ``Element` также пытается получить значение атрибута. Преимущество этого метода заключается в том, что вы можете предоставить значение по умолчанию, которое возвращается, если данный элемент фактически не имеет атрибута по данному имени.
Вот общий вид, для некоторого экземпляра Element.
E.get(key, default=None)
Аргументом key является имя атрибута, значение которого вы хотите получить.
- Если E имеет атрибут по этому имени, метод возвращает значение этого атрибута в виде строки.
- Если E не имеет такого атрибута, метод возвращает аргумент по умолчанию, который сам по умолчанию имеет значение None.
Вот пример:
>>> from lxml import etree
>>> node = etree.fromstring('<mount species="Jackalope"/>')
>>> print node.get('species')
Jackalope
>>> print node.get('source')
None
>>> print node.get('source', 'Unknown')
Unknown
>>>
9.9. Element.getchildren(): получить дочерние элементы¶
Для экземпляра E Element этот метод возвращает список всех дочерних элементов E:
E.getchildren()
Вот пример:
>>> xml = '''<corral><horse n="2"/><cow n="17"/>
... <cowboy n="2"/></corral>'''
>>> pen = etree.fromstring(xml)
>>> penContents = pen.getchildren()
>>> for content in penContents:
... print "%-10s %3s" % (content.tag, content.get("n", "0"))
...
horse 2
cow 17
cowboy 2
>>>
9.10. Element.getiterator(): Сделать итератор для перемещения поддерева¶
Иногда вы хотите пройти через весь или часть документа, глядя на все элементы в порядке документа. Аналогичным образом, вы можете пройти через весь или часть документа и искать все вхождения определенного типа элемента.
Метод .getiterator() на экземпляре Element создает итератор Python, который сообщает Python, как посещать элементы этими способами. Вот общий вид для экземпляра Element E:
E.getiterator(tag=None)
- Если вы опустите аргумент, вы получите итератор, который сначала посещает E, а затем все его дочерние элементы и их дочерние элементы в обходе порядка в этом поддереве.
- Если вы хотите посетить только элементы с определенным именем тега, передайте имя тега в качестве аргумента.
Предпросмотр обхода дерева означает, что мы сначала посещаем корень, затем поддеревья слева направо (то есть в порядке документа). Это также называется переходом по глубине: мы посещаем корень, потом его первый ребенок, потом первый его первый ребенок и т. Д., Пока не закончим потомков. Затем мы возвращаемся к последнему элементу с большим количеством детей и повторяем.
Вот пример, показывающий обход всего дерева. Во-первых, диаграмма, показывающая древовидную структуру:
Обход этого дерева происходит в следующем порядке: a, b, c, d, e.
>>> xml = '''<a><b><c/><d/></b><e/></a>'''
>>> tree = etree.fromstring(xml)
>>> walkAll = tree.getiterator()
>>> for elt in walkAll:
... print elt.tag,
...
a b c d e
>>>
В этом примере мы посещаем только bird узлы .
>>> xml = '''<bio>
... <bird type="Bushtit"/>
... <butterfly type="Mourning Cloak"/>
... <bird type="Mew Gull"/>
... <group site="Water Canyon">
... <snake type="Sidewinder"/>
... <bird type="Verdin"/>
... </group>
... <bird type="Pygmy Nuthatch"/>
... </bio>'''
>>> root = etree.fromstring(xml)
>>> for elt in root.getiterator('bird'):
... print elt.get('type', 'Unknown')
...
Bushtit
Mew Gull
Verdin
Pygmy Nuthatch
>>>
В приведенном выше примере обратите внимание, что итератор посещает элемент Verdin, даже если он не является прямым дочерним элементом корневого элемента.
9.11. Element.getroottree(): найдите элемент ElementTree, содержащий этот элемент¶
Для любого экземпляра E тот вызов метода возвращает экземпляр ElementTree, который содержит E:
E.getroottree()
9.12. Element.insert(): вставить новый дочерний элемент¶
Используйте метод .insert() в экземпляре E элемента, чтобы добавить новый дочерний элемент elt в произвольное положение. (Чтобы добавить новый дочерний элемент элемента в последнюю позицию, см. Раздел 9.3, «Element.append (): Добавить новый дочерний элемент».)
E.insert(index, elt)
Аргумент index указывает позицию, в которую вставлен элемент elt. Например, если вы укажете индекс 0, новый ребенок будет вставлен перед любыми другими дочерними элементами E.
Модуль lxml вполне разрешителен относительно значений аргумента index: если он отрицательный или больше, чем позиция последнего существующего дочернего элемента, новый ребенок добавляется после всех существующих дочерних элементов.
Вот пример, показывающий вставки в позициях 0 и 2.
>>> node = etree.fromstring('<a><c0/><c1/><c2/></a>')
>>> newKid = etree.Element('c-1', laugh="Hi!")
>>> node.insert(0, newKid)
>>> etree.tostring(node)
'<a><c-1 laugh="Hi!"/><c0/><c1/><c2/></a>'
>>> newerKid = etree.Element('cn')
>>> node.insert(2, newerKid)
>>> etree.tostring(node)
'<a><c-1 laugh="Hi!"/><c0/><cn/><c1/><c2/></a>'
>>>
9.13. Element.items(): создавать имена атрибутов и значения¶
Для любого экземпляра E метод .items() возвращает атрибуты, как если бы они были словарем, и вы вызывали метод .items() в этом словаре: результатом является список двухэлементных кортежей (имя, значение), по одному для каждого атрибута XML E.
Значения атрибутов возвращаются в определенном порядке.
Вот пример.
>>> node = etree.fromstring("<event time='1830' cost='3.50' rating='nc-03'/>")
>>> node.items()
[('cost', '3.50'), ('time', '1830'), ('rating', 'nc-03')]
>>>
9.14. Element.iterancestors(): Найдите предков элемента¶
Предками элемента являются его родительский элемент, родительский родительский элемент и т. Д. Вплоть до корневого элемента дерева. Для любого экземпляра E элемента этот метод возвращает итератор, который посещает предков E в обратном порядке документа:
E.iterancestors(tag=None)
Если вы опустите аргумент, итератор посетит всех предков. Если вы хотите посетить только предков с определенным именем тега, передайте это имя тега в качестве аргумента.
Примеры:
>>> xml = '''<class sci='Aves' eng='Birds'>
... <order sci='Strigiformes' eng='Owls'>
... <family sci='Tytonidae' eng='Barn-Owls'>
... <genus sci='Tyto'>
... <species sci='Tyto alba' eng='Barn Owl'/>
... </genus>
... </family>
... </order>
... </class>'''
>>> root = etree.fromstring(xml)
>>> barney = root.xpath('//species') [0]
>>> print "%s: %s" % (barney.get('sci'), barney.get('eng'))
Tyto alba: Barn Owl
>>> for ancestor in barney.iterancestors():
... print ancestor.tag,
genus family order class
>>> for fam in barney.iterancestors('family'):
... print "%s: %s" % (fam.get('sci'), fam.get('eng'))
Tytonidae: Barn-Owls
9.15. Element.iterchildren(): Найти всех детей¶
Для экземпляра E Element этот метод возвращает итератор, который выполняет итерацию по всем дочерним элементам E.
E.iterchildren(reversed=False, tag=None)
Обычно результирующий итератор будет посещать детей в порядке документа. Однако, если вы пройдете обратный = True, он будет посещать их в обратном порядке.
Если вы хотите, чтобы итератор посещал только детей с определенным именем N, передайте аргумент tag = N.
Пример:
>>> root=et.fromstring("<mom><aaron/><betty/><clarence/><dana/></mom>")
>>> for kid in root.getchildren():
... print kid.tag
aaron
betty
clarence
dana
>>> for kid in root.iterchildren(reversed=True):
... print kid.tag
...
dana
clarence
betty
aaron
>>>
9.16. Element.iterdescendants(): Найти всех потомков¶
Термин descendants относится к детям элемента, их детям и т. Д. Вплоть до листьев дерева документов.
Для экземпляра E этот метод возвращает итератор, который посещает всех потомков E в порядке документа.
E.iterdescendants(tag=None)
Если вы хотите, чтобы итератор посещал только элементы с определенным именем тега N, передайте аргумент tag = N.
Пример:
>>> xml = '''<root>
... <grandpa>
... <dad>
... <yuo/>
... </dad>
... </grandpa>
... </root>'''
>>> root = etree.fromstring(xml)
>>> you = root.xpath('.//yuo')[0]
>>> for anc in you.iterancestors():
... print anc.tag,
dad grandpa root
>>>
9.17. Element.itersiblings(): Найти других детей одного и того же родителя¶
Для любого экземпляра E этот метод возвращает итератор, который посещает всех родных братьев E, то есть дочерние элементы его родителя, в порядке документа, но не указывая E.
E.itersiblings(preceding=False)
Если preceding аргумент имеет значение false, итератор будет посещать братьев и сестер, следующих за E в порядке документа. Если preceding=True, итератор посетит братьев и сестер, которые предшествуют E в порядке документа.
Пример:
>>> root=etree.fromstring(
... "<mom><aaron/><betty/><clarence/><dana/></mom>")
>>> betty=root.find('betty')
>>> for sib in betty.itersiblings(preceding=True):
... print sib.tag
...
aaron
>>> for sib in betty.itersiblings():
... print sib.tag
...
clarence
dana
>>>
9.18. Element.keys(): найти все имена атрибутов¶
Для любого экземпляра E этот метод возвращает список имен атрибутов XML элемента, в определенном порядке.
E.keys()
Вот пример:
>>> node = etree.fromstring("<event time='1830' cost='3.50' rating='nc-03'/>")
>>> node.keys()
['time', 'rating', 'cost']
>>>
9.19. Element.remove(): удалить дочерний элемент¶
Чтобы удалить дочерний элемент C из экземпляра E, используйте этот вызов метода.
E.remove(C)
Если C не является дочерним элементом E, этот метод вызывает исключение ValueError.
9.20. Element.set(): установить значение атрибута¶
Чтобы создать или изменить атрибут с именем A для значения V в экземпляре E элемента, используйте этот метод:
E.set(A, V)
Вот пример.
>>> node = etree.Element('div', id='u401')
>>> etree.tostring(node)
'<div id="u401"/>'
>>> node.set('class', 'flyer')
>>> etree.tostring(node)
'<div id="u401" class="flyer"/>'
>>> node.set('class', 'broadside')
>>> etree.tostring(node)
'<div id="u401" class="broadside"/>'
>>>
Этот метод является одним из двух способов создания или изменения значения атрибута. Другой метод - изменять значения в словаре .attrib экземпляра Element.
9.21. Element.xpath(): оценка выражения XPath¶
Чтобы оценить выражение XPath с использованием некоторого экземпляра Element как контекстного узла:
E.xpath(s[, namespaces=N][, var=value][, ...])
Для общего обсуждения использования XPath см. Раздел 10 «Обработка XPath».
- s
- Выражение XPath для оценки.
- N
- Карта пространства имен, которая связывает префиксы пространства имен с NSURI; см. раздел 4.3 «Карты пространства имен». Карта пространства имен используется для интерпретации префиксов пространства имен в выражении XPath.
- var=value
- Вы можете использовать дополнительные аргументы ключевых слов для определения значений переменных XPath, которые будут использоваться при оценке s. Например, если вы передадите аргумент count = 17, значение переменной $ count в выражении XPath будет равно 17.
Возвращаемое значение может быть любым:
- Список нулевых или более выбранных экземпляров элементов.
- Значение bool Python для тестов true/false.
- Значение float Python для числовых результатов.
- Строка для строкового результата.
