Python - 解析XML - 空元素的问题

时间:2017-05-10 16:15:22

标签: python xml xml-parsing

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

<script type="text/javascript">

$( document ).ready(function() {
    $('#twit-follow-count').html('<?php echo $followers_count; ?>');
});

</script>

我循环遍历以下元素(Id_Customer,Segment,Extrainfo,zipcode,street)以构建一个列表,然后我将导出到.csv文件。

我的代码生成以下输出:[xyz1,abc1,info2,zzwy,c2 ..]虽然我希望找不到的元素在列表中输入为“空”,以便我的列表包含:[xyz1 ,abc1,info2,空,空,zzwy,c2 ..]

以下是我的代码示例:

<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>

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

2 个答案:

答案 0 :(得分:0)

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

我想以下内容可能有效(未经测试),每个客户都在一个单独的列表中(如csv文件中的行),然后插入到一般的list_prn列表中。当然,在构建csv文件时,您必须遍历列表。

如果您真的想要一个列表中的所有元素值,您可以跳过创建cust列表并将值直接插入list_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)

答案 1 :(得分:0)

您的主要问题是,您实际上只是将数据从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代码,但老实说可能是更好的方法。那就是使用类或字典对数据进行排序:每个<Customer>标记一个字典或对象。你正在做什么我会说创建一个类可能有点矫枉过正,所以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中创建的列表。 for customer in customers:对于每次迭代:
    1. 循环浏览您在步骤3中创建的列表。 for key in keys:
    2. 对于每个键,从dict获取相应的值,并将该值添加到CSV输出中。假设你有一个名为“csv”的打开文件对象,这样的东西就可以工作:csv.write(customer[key])(当然你也要在这一点上把逗号写入文件,除非它是最后一次迭代keys循环,然后编写换行符。您可以使用key == keys[-1]
    3. 对其进行测试