提取XML属性

0 投票
3 回答
1212 浏览
提问于 2025-04-17 14:09

我有一个XML文件,里面有几千条记录,格式是这样的:

<custs>
    <record cust_ID="B123456@Y1996" l_name="Jungle" f_name="George" m_name="OfThe" city="Fairbanks" zip="00010" current="1" />
    <record cust_ID="Q975697@Z2000" l_name="Freely" f_name="I" m_name="P" city="Yellow River" zip="03010" current="1" />
    <record cust_ID="M7803@J2323" l_name="Jungle" f_name="Jim" m_name="" city="Fallen Arches" zip="07008" current="0" />
</custs>
    #   (I know it's not normalized.  This is just sample data)

我该如何把它转换成CSV格式或者用制表符分隔的文件呢?我知道可以用Python里的re.compile()来硬编码实现,但我觉得应该有更简单的方法,而且能适用于不同的XML文件格式。

我在这里找到了一些关于属性的讨论,(Beautifulsoup无法通过attrs=class提取数据, 用beautifulsoup提取属性值),这些讨论让我快要找到解决办法了:

#  Python 3.30
#
from bs4 import BeautifulSoup
import fileinput

Input = open("C:/Python/XML Tut/MinGrp.xml", encoding = "utf-8", errors = "backslashreplace")
OutFile = open('C:/Python/XML Tut/MinGrp_Out.ttxt', 'w', encoding = "utf-8", errors = "backslashreplace")

soup = BeautifulSoup(Input, features="xml")

results = soup.findAll('custs', attrs={})

# output = results   [0]#[0]

for each_tag in results:
    cust_attrb_value = results[0]
#       print (cust_attrb_value)
    OutFile.write(cust_attrb_value)

OutFile.close()

接下来(最后一步)该怎么做呢?

3 个回答

-1
<product product_id='66656432' name='munch'><category>men</category></product>

在Beautiful Soup这个库里,

product=soup.find("product",attrs={})

你可以用属性来获取数据,比如用product["name"]来访问产品的名称。

2

如果你的数据格式正确,也就是说,使用了标准的XML格式,那么你可以考虑使用lxml,而不是BeautifulSoup。使用lxml时,你可以先读取文件,然后对它应用DOM逻辑,包括使用XPath查询。通过XPath查询,你可以获取lxml对象,这些对象代表你感兴趣的每一个节点,从中提取你需要的数据,然后用像csv模块这样的工具,将数据重新写成你想要的格式。

具体来说,在lxml的文档中,可以查看以下教程:

1

我也不建议用BeautifulSoup来做这个,虽然我喜欢lxml,但那需要额外安装。如果你不想麻烦的话,用Python自带的ElementTree模块就能简单搞定。

像这样:

import xml.etree.ElementTree as ET
import sys
tree=ET.parse( 'test.xml' )
root=tree.getroot()
rs=root.getchildren()
keys = rs[0].attrib.keys()
for a in keys: sys.stdout.write(a); sys.stdout.write('\t')
sys.stdout.write('\n')
for r in rs:
    assert keys == r.attrib.keys()
    for k in keys: sys.stdout.write( r.attrib[k]); sys.stdout.write('\t')
    sys.stdout.write('\n')

在Python 3中,这段代码会输出:

zip m_name  current city    cust_ID l_name  f_name  
00010   OfThe   1   Fairbanks   B123456@Y1996   Jungle  George  
03010   P   1   Yellow River    Q975697@Z2000   Freely  I   
07008       0   Fallen Arches   M7803@J2323 Jungle  Jim 

需要注意的是,在Python 2.7中,属性的顺序会有所不同。如果你想让它们以特定的顺序输出,就得对“keys”这个列表进行排序。

这里的assert语句是用来检查所有行的属性是否一致。如果你的元素中确实有缺失或不同的属性,那你就需要处理这些差异,并为缺失的值提供默认值。(在你的示例数据中,有一个空值(m_name=""),而不是缺失值。你可能需要检查一下这个输出的使用者是否能正确处理这种情况,或者为这种情况添加一些特别的处理逻辑。)

撰写回答