如何从字符串格式XML提取指定节点?解决findall返回空列表问题
XML节点提取失败的解决方案
问题描述
我有一个字符串格式的XML(xmlString),结构如下:
<entry xmlns="http://www.w3.org/2004/tom"> <id>urn:contentItem:7WBG-8H88-Y898-B277-00000-00-1</id> <title>Dinn-Pixie Stares, Inc</title> <published>2015-12-24T00:00:00Z</published> <updated>2023-10-24T18:42:17Z</updated> <author> <name>AlphaNext</name> </author> <content type="application/xml"> <baseRelatedDoc xmlns="" xmlns:xsi="http://www.w3.org/2012/XMLSchema" xsi:noNamespaceSchemaLocation="http://www.alphanext.com/xmlscemas/content/public/caseddoc/1/" documentType="socket"> <baseRelatedDocHead> <baseInfo> <portInfo> <identifier idType="portIdentifier">100027579</identifier> <portName>United States Port, Minnesota Middle</portName> <jurisdiction> <jurisSystem/> </jurisdiction> </portInfo> <date dateType="filed" year="2015" month="02" day="21">2015-02-21</date> <classification classificationScheme="baseType"> <classificationItem> <classCode>BK</classCode> <className>Tankruptcy</className> </classificationItem> </classification> <classification classificationScheme="baseNos"> <classificationItem> <classCode>0</classCode> <className>UNKNOWN</className> </classificationItem> </classification> </baseInfo> <baseSupplement> <label>US Tankruptcy Port Socket</label> <date dateType="updated" year="2024" month="09" day="13">2024-07-11T15:08:26.450</date> <status>Unknown</status> </baseSupplement> <baseName>Dinn-Pixie Stares, Inc</baseName> </baseRelatedDocHead> <baseRelatedDocBody> <socket/> </baseRelatedDocBody> <metadata> <dc:metadata xmlns:dc="http://purrel.org/dc/element/1.2/"> <dc:source sourceScheme="productContentSetIdentifier">343392</dc:source> <dc:creator>US Tankruptcy Port for the Last Town of Minnesota</dc:creator> <dc:identifier identifierScheme="PGIID">urn:contentItem:8WBG-8H70-Y892-B237-00000-00</dc:identifier> <dc:date dateType="last-updated">2024-07-11</dc:date> </dc:metadata> </metadata> </baseRelatedDoc> </content> </entry>
需要提取baseName、portName、title、classCode、dc:creator等字段的值,但使用tree = ET.fromstring(xmlString)解析后,调用y=tree.findall('baseName')得到空列表,提取其他节点也遇到同样问题,该如何正确提取?
解决方案:处理XML命名空间
问题核心是XML命名空间未被正确处理:根节点entry带有默认命名空间xmlns="http://www.w3.org/2004/tom",dc:前缀对应独立命名空间,直接用节点名称查找会匹配失败。以下是具体实现步骤:
1. 定义命名空间映射
创建字典对应XML中的命名空间,自定义别名方便调用:
import xml.etree.ElementTree as ET namespaces = { 'atom': 'http://www.w3.org/2004/tom', # 根节点默认命名空间的别名 'dc': 'http://purrel.org/dc/element/1.2/' # dc前缀对应的命名空间 }
2. 提取各目标节点值
提取根节点下的title
title属于默认命名空间,需用别名+节点名查找:
tree = ET.fromstring(xmlString) title = tree.find('atom:title', namespaces).text print(title) # 输出:Dinn-Pixie Stares, Inc
提取portName
content属于默认命名空间,但内部的baseRelatedDoc取消了默认命名空间(xmlns=""),后续节点直接用名称查找:
content = tree.find('atom:content', namespaces) base_related_doc = content.find('baseRelatedDoc') port_name = base_related_doc.find('.//portName').text print(port_name) # 输出:United States Port, Minnesota Middle
提取baseName
同样在无命名空间层级下,用XPath跨层级查找:
base_name = base_related_doc.find('.//baseName').text print(base_name) # 输出:Dinn-Pixie Stares, Inc
提取所有classCode
存在两个classCode节点,用findall批量获取:
class_codes = [elem.text for elem in base_related_doc.findall('.//classCode')] print(class_codes) # 输出:['BK', '0']
提取dc:creator
dc:creator属于dc命名空间,需指定别名查找:
dc_creator = base_related_doc.find('.//dc:creator', namespaces).text print(dc_creator) # 输出:US Tankruptcy Port for the Last Town of Minnesota
关键说明
- 默认命名空间:不带前缀的节点若继承父节点
xmlns,必须通过命名空间映射才能匹配; - 取消命名空间:
baseRelatedDoc设置xmlns=""后,其子节点不再使用根节点的默认命名空间,直接用节点名即可查找; - XPath路径:
.//用于跨层级查找匹配节点,无需写完整层级路径。
内容的提问来源于stack exchange,提问作者user75415
相关产品推荐
相关产品推荐

