Python 删除太多元素之间的多个XML元素

Python 删除太多元素之间的多个XML元素,python,xml,xml-parsing,lxml,elementtree,Python,Xml,Xml Parsing,Lxml,Elementtree,我有一些XML,如下所示: <FirstLevel> <item1>Val1</item1> <item2>Val2</item2> <item3>Val3</item3> <item4>Val4</item4> <item5>Val5</item5> </FirstLevel> 使用lxml,我知道如何查找it

我有一些XML,如下所示:

<FirstLevel>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
</FirstLevel>

使用
lxml
,我知道如何查找
item1
item5
,因此我只需要知道如何构建介于这两者之间的某种XML元素列表。

您可以使用和的组合,例如:

from lxml.etree import fromstring, tostring

data = """<FirstLevel>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
</FirstLevel>
"""

tree = fromstring(data)
node_start = "item1"
node_end = "item5"

parent = tree.xpath("//FirstLevel")[0]
for node in parent.xpath("*[preceding-sibling::%s and following-sibling::%s]" % (node_start, node_end)):
    parent.remove(node)

print(tostring(tree))

多亏了alecxe,我找到了解决方案。他的答案对于所描述的案例非常有效,但如果我们有多个item1-item5元素的实例(请参阅我对他的答案的评论,以便更好地理解),那么他的答案就不起作用(即使有他的更新)

无论如何,我找到了另一个解决方案(我认为更简单、更具python风格):

从lxml.etree导入fromstring,tostring
data=”“”
瓦尔1
瓦尔2
Val3
瓦尔4
瓦尔5
瓦尔1
瓦尔2
Val3
瓦尔4
瓦尔5
"""
tree=fromstring(数据)
item1_list=tree.findall(“item1”)
对于项目1_列表中的项目1:
next_node=item1.getnext()
而next_node.tag!=“项目5”:
tree.remove(下一个_节点)
next_node=item1.getnext()
打印(tostring(树))

alecxe comment还提供了一个适合我的解决方案:

从lxml.etree导入fromstring,tostring

data = """<FirstLevel>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
</FirstLevel>
"""

tree = fromstring(data)
node_start = "item1"
node_end = "item5"

parent = tree.xpath("//FirstLevel")[0]
# Remove first section
for node in parent.xpath("*[(preceding-sibling::item1)[1] and (following-sibling::item5)[3]]"):
    parent.remove(node)
# Remove second section
for node in parent.xpath("*[(preceding-sibling::item1)[2] and (following-sibling::item5)[2]]"):
    parent.remove(node)
# Remove last section
for node in parent.xpath("*[(preceding-sibling::item1)[3] and (following-sibling::item5)[last()]]"):
    parent.remove(node)

print(tostring(tree))
data=”“”
瓦尔1
瓦尔2
Val3
瓦尔4
瓦尔5
瓦尔1
瓦尔2
Val3
瓦尔4
瓦尔5
瓦尔1
瓦尔2
Val3
瓦尔4
瓦尔5
"""
tree=fromstring(数据)
node_start=“item1”
node_end=“item5”
parent=tree.xpath(“//FirstLevel”)[0]
#移除第一部分
对于parent.xpath中的节点(“*[(前面的兄弟姐妹::项目1)[1]和(后面的兄弟姐妹::项目5)[3]]”):
删除(节点)
#移除第二部分
对于parent.xpath中的节点(“*[(前面的兄弟姐妹::项目1)[2]和(后面的兄弟姐妹::项目5)[2]]”):
删除(节点)
#删除最后一节
对于parent.xpath中的节点(“*[(前面的同级::项目1)[3]和(后面的同级::项目5)[last()]]”):
删除(节点)
打印(tostring(树))

通过尝试多个值,我找到了正确的索引,可以放在
前面-
后面的兄弟姐妹中,但仍然没有真正理解其背后的逻辑,但至少对我来说是有效的。

在Python中,读取文件、删除所需部分然后重写文件通常要容易得多。idk,您使用的模块可能会有所不同。谢谢您的快速回答。在我的例子中,在一个更大的用例中访问该文件是很困难的,但是如果我找不到其他解决方案,我会考虑:)非常感谢您的回答,它在所描述的案例中非常有效。但是,如果我们考虑两次“ITEMN”元素(有ITEM1到ITEM5,再到ITEM5到ITEM5)的情况,它将删除第一个ITEM1和最后一个ITEM5之间的所有元素。我怎样才能再次获得项目1、项目5、项目1和项目5。我希望这是清楚的:)@filaton我想我明白你的意思。请查看更新。谢谢
<FirstLevel>
    <item1>Val1</item1>
    <item5>Val5</item5>
</FirstLevel>
item_start = "item1"
item_end = "item5"

parent = tree.xpath("//FirstLevel")[0]
for node_start in parent.xpath("%s" % item_start):
    for node in node_start.xpath("following-sibling::%s" % item_end):
        parent.remove(node)
from lxml.etree import fromstring, tostring

data = """<FirstLevel>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
</FirstLevel>
"""

tree = fromstring(data)

item1_list = tree.findall("item1")

for item1 in item1_list:
    next_node = item1.getnext()
    while next_node.tag != "item5":
        tree.remove(next_node)
        next_node = item1.getnext()

print(tostring(tree))
data = """<FirstLevel>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
    <item1>Val1</item1>
    <item2>Val2</item2>
    <item3>Val3</item3>
    <item4>Val4</item4>
    <item5>Val5</item5>
</FirstLevel>
"""

tree = fromstring(data)
node_start = "item1"
node_end = "item5"

parent = tree.xpath("//FirstLevel")[0]
# Remove first section
for node in parent.xpath("*[(preceding-sibling::item1)[1] and (following-sibling::item5)[3]]"):
    parent.remove(node)
# Remove second section
for node in parent.xpath("*[(preceding-sibling::item1)[2] and (following-sibling::item5)[2]]"):
    parent.remove(node)
# Remove last section
for node in parent.xpath("*[(preceding-sibling::item1)[3] and (following-sibling::item5)[last()]]"):
    parent.remove(node)

print(tostring(tree))