Python解析XML时出现空元素的问题

2024-04-19 09:26:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python和XML的新手,尝试通过解析下面的文件来提取几个元素。问题是有些元素是空的(例如客户xyz1没有任何地址信息)。在

<CAT>
  <Header>...</Header>
  <Add>...</Add>
  <Customer>
    <Id_Customer>xyz1</Id_Customer>
    <Segment>abc1</Segment>
    <Event>
      <Nature>info1</Nature>
      <Extrainfo>info2</Extrainfo>
    </Event>
</Customer>
<Customer>
    <Id_Customer>zzwy</Id_Customer>
    <Segment>c2</Segment>
    <Adress>
       <zipcode>77098</zipcode>
       <street>belaire drive</street>
       <number>5</number>
    </Adress>
</Customer>
<Customer>...</Customer>
</CAT>

我循环使用以下元素(Id_Customer、Segment、Extrainfo、zipcode、street),以建立一个列表,然后将其导出到.csv文件中。在

我下面的代码生成以下输出:[xyz1,abc1,info2,zzwy,c2….]同时我希望列表中没有找到的元素作为“empty”输入,这样我的列表将包含:[xyz1,abc1,info2,empty,empty,zzwy,c2….]

下面是我的代码示例:

^{pr2}$

我将非常感谢你的帮助。(我只能使用标准python库。)


Tags: 文件id元素street列表segmentcustomerempty
2条回答

看看方法findtextxml.etree(https://docs.python.org/3.6/library/xml.etree.elementtree.html),默认值。在

我猜在下面的列表中插入一个单独的列表(我猜是不是每个客户都会被插入到一个列表中)。当然,在构建csv文件时,必须遍历列表。在

如果您真的希望所有元素的值都在一个列表中,那么可以跳过cust list的创建,直接将这些值插入list\u prn中。在

这都说明顾客的所有子要素只存在一次。在

from xml.etree import ElementTree
import csv

list_prm = []

tree = ElementTree.parse('file.xml')
root = tree.getroot()

for elem in tree.iter('Customer'):
    # only the first customer_id
    customer_id = elem.find('Id_Customer')
    if customer_id is not None:
        # Create a separate list for each Customer,
        # only if there's Customer Id, skip creation otherwise
        cust = []

        cust.append(customer_id.text())
        cust.append(elem.findtext('Segment', default='empty'))
        cust.append(elem.findtext('Extrainfo', default='empty'))
        cust.append(elem.findtext('Address/street', default='empty'))
        cust.append(elem.findtext('Address/zipcode', default='empty'))

        list_prm.append(cust)


print(list_prm)

您的主要问题是,您实际上只是将数据从XML以几乎与您发现的相同的状态从XML发送到CSV。您所指的“空”元素不是空的,它们不存在于XML中。在

我可以想出两种方法来让这项工作做得更好。第一种方法是更改XML,使每个<Customer>元素以相同的顺序包含所有元素,即使这些元素是完全空的。换句话说,您的XML可能如下所示:

<Customer>
    <Id_Customer>xyz1</Id_Customer>
    <Segment>abc1</Segment>
    <Event>
      <Nature>info1</Nature>
      <Extrainfo>info2</Extrainfo>
    </Event>
    <Adress>
       <zipcode></zipcode>
       <street></street>
       <number></number>
    </Adress>
</Customer>
<Customer>
    <Id_Customer>zzwy</Id_Customer>
    <Segment>c2</Segment>
    <Event>
      <Nature></Nature>
      <Extrainfo></Extrainfo>
    </Event>
    <Adress>
       <zipcode>77098</zipcode>
       <street>belaire drive</street>
       <number>5</number>
    </Adress>
</Customer>

如果您愿意,您可以在Python代码中添加一个条件,将空字符串("")替换为单词“empty”,因为您指出了您希望它这样说。在

另一种方法可以生成更复杂的Python代码,但实际上可能是更好的方法。那就是使用类或dict对数据进行排序:每个<Customer>标记一个dict或object。对于你所做的,我想说创建一个类可能有点过头了,所以一个dict就足够了。(使用defaultdict而不是普通dict将允许您在找不到值时自动提供单词“empty”,因此我将对此进行研究。)

基本上,程序流程如下:

  1. 创建一个空列表来存储您的dicts。customers = []
  2. 循环遍历XML树中的<Customer>元素。对于每个客户:
    1. 创建一个新的dict并将其添加到列表中。customer={}customer=defaultdict("empty"),然后customers.append(customer)
    2. 循环遍历该元素的子元素,并为每个元素填充dict中的信息。类似customer[elem.tag]=elem.text的东西可能就是你要找的。在
  3. 创建要从中获取的所有dict键的列表,其顺序与CSV中的头相同。例如keys=["Id_Customer", "Segment", etc...]
  4. 循环查看在步骤1和2中创建的列表。e、 g.for customer in customers:对于每个迭代:
    1. 循环查看在步骤3中创建的列表。e、 g.for key in keys:
    2. 对于每个键,从dict中获取相应的值,并将该值添加到CSV输出中。假设您有一个名为“csv”的open file对象,类似这样的方法是可行的:csv.write(customer[key])(当然,此时您也希望将逗号写入文件,除非它是keys循环的最后一次迭代,然后改为写一个新行。你可以用key == keys[-1])来测试它

相关问题 更多 >