2016-10-19 2 views
1

Предположим, у вас есть lmxl.etree элемент с содержимым, например:Как создать подмножество документа с помощью lxml?

<root> 
    <element1> 
     <subelement1>blabla</subelement1> 
    </element1> 
    <element2> 
     <subelement2>blibli</sublement2> 
    </element2> 
</root> 

я могу использовать найти или методы XPath, чтобы получить что-то элемент визуализации что-то вроде:

<element1> 
    <subelement1>blabla</subelement1> 
</element1> 

Есть ли способ простой получить:

<root> 
    <element1> 
     <subelement1>blabla</subelement1> 
    </element1> 
</root> 

т.е. элемент интереса плюс все это предки вплоть до Docum корень?

+0

Вы хотите, чтобы все предки выбранного элемента? Как насчет братьев и сестер на разных уровнях, если их следует удалить? Ваш пример не дает понять. – audiodude

+0

Да, они также должны быть удалены .. результирующим подмножеством должны быть выбранные элементы плюс его предки «опустели» –

+0

Я хотел бы, чтобы вас доказали неправильно, но я не думаю, что вы найдете * простой * способ сделать это, например doc_root.strip_everything_but_child_by_xpath ('// some/xpath/element1'). Вам придется пройти DOM на основе того, где вы найдете свой элемент, и вырезать/удалить узлы вручную. – audiodude

ответ

2

Я не уверен, что есть что-то встроенное для него, но здесь это ужасно, «никогда не использовать его в реальной жизни» типа обхода с помощью iterancestors() parent iterator:

from lxml import etree as ET 

data = """<root> 
    <element1> 
     <subelement1>blabla</subelement1> 
    </element1> 
    <element2> 
     <subelement2>blibli</subelement2> 
    </element2> 
</root>""" 


root = ET.fromstring(data) 
element = root.find(".//subelement1") 

result = ET.tostring(element) 
for node in element.iterancestors(): 
    result = "<{name}>{text}</{name}>".format(name=node.tag, text=result) 

print(ET.tostring(ET.fromstring(result), pretty_print=True)) 

Печати :

<root> 
    <element1> 
    <subelement1>blabla</subelement1> 
    </element1> 
</root> 
+0

Ну, я отправил вопрос, есть ли элегантное встроенное решение. Я закончил тем, что сделал что-то похожее на ваш ответ, но я не понимаю, почему это так ужасно. Конечно, не очень элегантный, но я думаю, что он работает –

+0

@ B-K да, это было просто хорошее самокритицирование :) – alecxe

+0

Я думаю, что построение этого как струны несколько ужасно. С помощью 'lxml.builder.E' это можно сделать без создания XML с помощью форматирования строк. – BlackJack

1

следующий код удаляет элементы, которые не имеют никаких subelement1 потомков и не названы subelement1.

from lxml import etree 

tree = etree.parse("input.xml") # First XML document in question 

for elem in tree.iter(): 
    if elem.xpath("not(.//subelement1)") and not(elem.tag == "subelement1"): 
     if elem.getparent() is not None: 
      elem.getparent().remove(elem) 

print etree.tostring(tree) 

Выход:

<root> 
    <element1> 
    <subelement1>blabla</subelement1> 
    </element1> 
    </root>