2016-09-07 2 views
0

Учитывая следующий XML:LXML нерекурсивна полный тег

<node a='1' b='1'> 
    <subnode x='25'/> 
</node> 

Я хотел бы, чтобы извлечь тэг и все атрибуты первого узла, то есть дословный код:

<node a='1' b='1'> 

без подзоне.

Например, в Python, tostring возвращает слишком много:

from lxml import etree 
root = etree.fromstring("<node a='1' b='1'><subnode x='25'>some text</subnode></node>") 
print(etree.tostring(root)) 

возвращает

b'<node a="1" b="1"><subnode x="25">some text</subnode></node>' 

Следующая дает желаемый результат, но слишком многословен:

tag = root.tag 
for att, val in root.attrib.items(): 
    tag += ' '+att+'="'+val+'"' 
tag = '<'+tag+'>' 
print(tag) 

результат :

<node a="1" b="1"> 

Что является более простым (и гарантированным сохранением порядка атрибутов)?

+0

* «Гарантированный порядок сохранения атрибутов» * - это огромный запах кода. Что вы пытаетесь сделать с этим '' string? – Tomalak

+0

@Tomalak Я хочу построить новое дерево из некоторого более высокого уровня и некоторых узлов нижнего уровня (пропуская узлы промежуточного уровня), не испытывая проблем с фактическим перемещением поддерева и буферизацией узлов. – Marijn

+0

Если преобразование дерева является вашей целью, я бы рекомендовал посмотреть на XSLT. Это наиболее подходящий инструмент для этой задачи, а решения XSLT, как правило, намного более элегантны, чем эквивалентный код API DOM на императивном языке. Поместите достаточно полный входной документ и желаемый результат для этого. При этом порядок атрибутов несуществен в XML. Не создавайте никаких систем, зависящих от порядка атрибутов. – Tomalak

ответ

1

Вы можете удалить все подузлы.

from lxml import etree 

root = etree.fromstring("<node a='1' b='1'><subnode x='25'>some text</subnode></node>") 
for subnode in root.xpath("//subnode"): 
    subnode.getparent().remove(subnode) 

etree.tostring(root) # '<node a="1" b="1"/>' 

В качестве альтернативы вы можете использовать простое регулярное выражение. Заказ гарантирован.

import re 
res = re.search('<(.*?)>', etree.tostring(root)) 
res.group(1) # "node a='1' b='1'"