lxml에서 요소를 제거하는 방법
python의 lxml을 사용하여 속성의 내용을 기반으로 요소를 완전히 제거해야 합니다.예:
import lxml.etree as et
xml="""
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
"""
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
#remove this element from the tree
print et.tostring(tree, pretty_print=True)
이것을 인쇄하고 싶습니다.
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
다음과 같이 임시 변수를 저장하고 수동으로 인쇄하지 않고 이 작업을 수행할 수 있는 방법이 있습니까?
newxml="<groceries>\n"
for elt in tree.xpath('//fruit[@state=\'fresh\']'):
newxml+=et.tostring(elt)
newxml+="</groceries>"
xmlElement 메서드를 사용합니다.
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
bad.getparent().remove(bad) # here I grab the parent of the element to call the remove directly on it
print et.tostring(tree, pretty_print=True, xml_declaration=True)
만약 내가 @Acorn 버전과 비교해야 한다면, 제거할 요소가 xml의 root 노드 바로 아래에 있지 않더라도 내 것은 작동할 것입니다.
당신이 찾고 있는 것은remove기능.트리의 제거 방법을 호출하고 제거할 하위 요소를 전달합니다.
import lxml.etree as et
xml="""
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<punnet>
<fruit state="rotten">strawberry</fruit>
<fruit state="fresh">blueberry</fruit>
</punnet>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
"""
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state='rotten']"):
bad.getparent().remove(bad)
print et.tostring(tree, pretty_print=True)
결과:
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
나는 한가지 상황을 만났습니다.
<div>
<script>
some code
</script>
text here
</div>
div.remove(script)제거할 것입니다.text here의도하지 않은 부분.
여기에 답을 따라서, 나는 그것을 발견했습니다.etree.strip_elements나에게 더 나은 해결책입니다. 당신은 당신이 뒤에 있는 텍스트를 삭제할지 말지를 통제할 수 있습니다.with_tail=(bool)PARAM.
하지만 아직도 이것이 태그에 xpath 필터를 사용할 수 있는지 모르겠습니다.이것은 그냥 알려주기 위해서입니다.
여기 서류가 있습니다.
strip_elements(tree_or_element, *tag_names, with_tail=True)
트리 또는 하위 트리에서 제공된 태그 이름을 가진 모든 요소를 삭제합니다.이렇게 하면 요소와 요소의 모든 속성, 텍스트 내용 및 하위 트리를 포함한 전체 하위 트리가 제거됩니다.또한 명시적으로 설정하지 않는 한 요소의 꼬리 텍스트를 제거합니다.
with_tail키워드 인수 옵션을 False로 지정합니다.태그 이름은 와 같이 와일드카드를 포함할 수 있습니다.
_Element.iter.이렇게 해도 요소(또는 Element)는 삭제되지 않습니다.일치하더라도 전달한 트리 루트 요소).그것은 오직 후손들을 대할 뿐입니다.루트 요소를 포함하려면 이 함수를 호출하기 전에 태그 이름을 직접 확인합니다.
사용 예시:
strip_elements(some_element, 'simpletagname', # non-namespaced tag '{http://some/ns}tagname', # namespaced tag '{http://some/other/ns}*' # any tag from a namespace lxml.etree.Comment # comments )
이미 언급한 바와 같이, 사용할 수 있습니다.remove()트리에서 elements을(를) 삭제하는 방법:
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
bad.getparent().remove(bad)
그러나 그것은 그것을 포함한 요소를 제거합니다.tail, HTML과 같은 혼합 콘텐츠 문서를 처리하는 경우 문제가 됩니다.
<div><fruit state="rotten">avocado</fruit> Hello!</div>
된다
<div></div>
당신이 항상 원하지 않는 것을 가정합니다 :) 요소만 제거하고 꼬리를 유지하는 도우미 기능을 만들었습니다.
def remove_element(el):
parent = el.getparent()
if el.tail.strip():
prev = el.getprevious()
if prev:
prev.tail = (prev.tail or '') + el.tail
else:
parent.text = (parent.text or '') + el.tail
parent.remove(el)
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
remove_element(bad)
이렇게 하면 꼬리 텍스트가 유지됩니다.
<div> Hello!</div>
lxml의 html을 사용하여 다음을 해결할 수도 있습니다.
from lxml import html
xml="""
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
"""
tree = html.fromstring(xml)
print("//BEFORE")
print(html.tostring(tree, pretty_print=True).decode("utf-8"))
for i in tree.xpath("//fruit[@state='rotten']"):
i.drop_tree()
print("//AFTER")
print(html.tostring(tree, pretty_print=True).decode("utf-8"))
다음을 출력해야 합니다.
//BEFORE
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
//AFTER
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
그remove함수는 트리에서 요소를 분리하므로 XML 노드(Element, PI 또는 Comment), 그 내용(후속 항목) 및tail 여기를 보존하는 겁니다 여기서, 그를 보호하는 것은tail텍스트는 공백과 무시 가능한 공백으로 간주될 수 있는 새 줄만 포함하기 때문에 불필요합니다.
요소(및 해당 내용)를 제거하고 해당 요소를 보존하려면 다음과 같이 하십시오.tail, 다음 기능을 사용할 수 있습니다.
def remove_node(child, keep_content=False):
"""
Remove an XML element, preserving its tail text.
:param child: XML element to remove
:param keep_content: ``True`` to keep child text and sub-elements.
"""
parent = child.getparent()
parent_text = parent.text or u""
prev_node = child.getprevious()
if keep_content:
# insert: child text
child_text = child.text or u""
if prev_node is None:
parent.text = u"{0}{1}".format(parent_text, child_text) or None
else:
prev_tail = prev_node.tail or u""
prev_node.tail = u"{0}{1}".format(prev_tail, child_text) or None
# insert: child elements
index = parent.index(child)
parent[index:index] = child[:]
# insert: child tail
parent_text = parent.text or u""
prev_node = child.getprevious()
child_tail = child.tail or u""
if prev_node is None:
parent.text = u"{0}{1}".format(parent_text, child_tail) or None
else:
prev_tail = prev_node.tail or u""
prev_node.tail = u"{0}{1}".format(prev_tail, child_tail) or None
# remove: child
parent.remove(child)
데모는 다음과 같습니다.
from lxml import etree
tree = etree.XML(u"<root>text <bad>before <bad>inner</bad> after</bad> tail</root>")
bad1 = tree.xpath("//bad[1]")[0]
remove_node(bad1)
etree.dump(tree)
# <root>text tail</root>
컨텐츠를 보존하려면 다음 작업을 수행할 수 있습니다.
tree = etree.XML(u"<root>text <bad>before <bad>inner</bad> after</bad> tail</root>")
bad1 = tree.xpath("//bad[1]")[0]
remove_node(bad1, keep_content=True)
etree.dump(tree)
# <root>text before <bad>inner</bad> after tail</root>
언급URL : https://stackoverflow.com/questions/7981840/how-to-remove-an-element-in-lxml
'programing' 카테고리의 다른 글
| 드롭다운 상자에서 선택한 항목을 설정하는 방법 (0) | 2023.10.19 |
|---|---|
| 인덱싱 Pandas 데이터 프레임: 정수 행, 명명된 열 (0) | 2023.10.19 |
| FROM 절에서 하위 쿼리를 사용하여 MariaDB 쿼리를 최적화하려면 어떻게 해야 합니까? (0) | 2023.10.19 |
| "#TYPE" 라인 없이 PowerShell을 사용하여 CSV를 출력하려면 어떻게 해야 합니까? (0) | 2023.10.19 |
| C 및 Linux에서 소켓에 사용 가능한 데이터 양을 확인하는 방법 (0) | 2023.10.14 |