【问题标题】:XML remove child based on the subelement value in PythonXML根据Python中的子元素值删除子元素
【发布时间】:2021-11-11 11:12:29
【问题描述】:

我正在尝试根据子元素“id”值从根中删除多个“交易”子元素。 我有 id 列表,并希望有一个循环来删除整个孩子的“交易”。

XML 代码如下。

<holdings>
  <Traded>
    <positionName>position1</positionName>
    <id type="ISIN" exchange="BB">BE154</id>
    <amount>400</amount>
    <price currency="EUR">44.000000000000</price>
  </Traded>
  <Traded>
    <positionName>position2</positionName>
    <id type="ISIN" exchange="FP">FR200</id>
    <amount>200</amount>
    <price currency="EUR">58.240000000000</price>
  </Traded>
  <Traded>
    <positionName>position3</positionName>
    <id type="ISIN" exchange="UN">US400</id>
    <amount>100</amount>
    <price currency="USD">413.310000000000</price>
  </Traded>
  <Traded>
    <positionName>position4</positionName>
    <id type="ISIN" exchange="UN">US15</id>
    <amount>50000</amount>
    <price currency="USD">20.120000000000</price>
  </Traded>
</holdings>

不起作用的 Python 代码:

import xml.etree.ElementTree as ET

tree = ET.parse("positions.xml")
root = tree.getroot()

removelist = ["BE154", "FR200", "US400", "US15"]

for child in root:
    for subelement in root.iter("id"):
        for subelement.text in removelist:
            child.remove

我们将不胜感激。

【问题讨论】:

  • 一方面,你没有打电话给.remove...

标签: python xml


【解决方案1】:

这似乎可以解决问题。 (为了封装示例,我嵌入了 XML。)

import xml.etree.ElementTree as ET

root = ET.fromstring(
    """
<holdings>
  <Traded>
    <positionName>position1</positionName>
    <id type="ISIN" exchange="BB">BE154</id>
    <amount>400</amount>
    <price currency="EUR">44.000000000000</price>
  </Traded>
  <Traded>
    <positionName>position2</positionName>
    <id type="ISIN" exchange="FP">FR200</id>
    <amount>200</amount>
    <price currency="EUR">58.240000000000</price>
  </Traded>
  <Traded>
    <positionName>position3</positionName>
    <id type="ISIN" exchange="UN">US400</id>
    <amount>100</amount>
    <price currency="USD">413.310000000000</price>
  </Traded>
  <Traded>
    <positionName>position4</positionName>
    <id type="ISIN" exchange="UN">US15</id>
    <amount>50000</amount>
    <price currency="USD">20.120000000000</price>
  </Traded>
</holdings>
"""
)

removelist = {"BE154", "FR200", "US400", "US15"}

for child in root[:]:  # `[:]` to take a copy of the list since we'd modify it
    id_element = child.find("id")
    if id_element is None:  # no ID, so keep this one
        continue
    trade_id = id_element.text
    if trade_id in removelist:
        root.remove(child)

print(ET.tostring(root, encoding="unicode"))

输出是

<holdings>
  <Traded>
    <positionName>position2</positionName>
    <id type="ISIN" exchange="FP">FR200</id>
    <amount>200</amount>
    <price currency="EUR">58.240000000000</price>
  </Traded>
  <Traded>
    <positionName>position4</positionName>
    <id type="ISIN" exchange="UN">US15</id>
    <amount>50000</amount>
    <price currency="USD">20.120000000000</price>
  </Traded>
</holdings>

【讨论】:

  • 它似乎非常接近解决方案,但它删除了 4 个孩子中的 2 个。你知道为什么吗?
  • 啊,是的,我的错。那是因为我们正在修改子列表,Python 会感到困惑。在编辑中修复:)
  • 你知道为什么trade_id = child.find("id").text 会触发error:'NoneType' object has no attribute 'text'吗?我加载大型 xml 并收到此错误。
  • 因为其中一个交易没有id 孩子。
  • 通过添加对这种情况的保护。查看我的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多