如何用Python minidom筛选XML中的WORK类型邮箱地址?
问题
需要用Python提取XML中所有属于WORK类型的邮箱地址,筛选依据是<wd:ID wd:type="Communication_Usage_Type_ID">WORK</wd:ID>元素,目标是获取对应的<wd:Email_Address>内容。
目标XML示例
<?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schema.xmlsoap.org/soap/envelope/"> <env:Body> <wd:Get_Working_Response xmlns:wd="urn:com.workway/bsvc" wd:version="v40.1"> <wd:Request_Criteria> <wd:Transaction_Log_Criteria_Data> </wd:Transaction_Log_Criteria_Data> <wd:Field_And_Parameter_Criteria_Data> </wd:Field_And_Parameter_Criteria_Data> <wd:Eligibility_Criteria_Data> </wd:Eligibility_Criteria_Data> </wd:Request_Criteria> <wd:Response_Filter> </wd:Response_Filter> <wd:Response_Group> </wd:Response_Group> <wd:Response_Results> </wd:Response_Results> <wd:Response_Data> <wd:Worker> <wd:Worker_Reference> <wd:ID wd:type="WID">787878787878787</wd:ID> <wd:ID wd:type="Employee_ID">123456</wd:ID> </wd:Worker_Reference> <wd:Worker_Descriptor>John Smith</wd:Worker_Descriptor> <wd:Worker_Data> <wd:Worker_ID>123456</wd:Worker_ID> <wd:User_ID>jsmith</wd:User_ID> <wd:Personal_Data> <wd:Email_Address_Data> <wd:Email_Address>jsmith2222@gmail.com</wd:Email_Address> <wd:Usage_Data wd:Public="0"> <wd:Type_Data wd:Primary="1"> <wd:Type_Reference> <wd:ID wd:type="WID">000000000000000</wd:ID> <wd:ID wd:type="Communication_Usage_Type_ID">HOME</wd:ID> </wd:Type_Reference> </wd:Type_Data> </wd:Usage_Data> <wd:Email_Reference> <wd:ID wd:type="WID">99999999999999999999999</wd:ID> <wd:ID wd:type="Email_ID">EMAIL_REFERENCE-3-3960</wd:ID> </wd:Email_Reference> <wd:ID>EMAIL_REFERENCE-3-3960</wd:ID> </wd:Email_Address_Data> <wd:Email_Address_Data> <wd:Email_Address>jsmith@something.com</wd:Email_Address> <wd:Usage_Data wd:Public="1"> <wd:Type_Data wd:Primary="1"> <wd:Type_Reference> <wd:ID wd:type="WID">999999999999999999999999999</wd:ID> <wd:ID wd:type="Communication_Usage_Type_ID">WORK</wd:ID> </wd:Type_Reference> </wd:Type_Data> </wd:Usage_Data> <wd:Email_Reference> <wd:ID wd:type="WID">999999999999999999999999</wd:ID> <wd:ID wd:type="Email_ID">EMAIL_REFERENCE-3-4017</wd:ID> </wd:Email_Reference> <wd:ID>EMAIL_REFERENCE-3-4017</wd:ID> </wd:Email_Address_Data> </wd:Personal_Data> </wd:Worker_Data> </wd:Worker> </wd:Response_Data> </wd:Get_Working_Response> </env:Body> </env:Envelope>
现有代码(已筛选出包含WORK的ID元素,但无法关联到对应的Email_Address_Data)
xmlDoc = minidom.parse('XML_Example.xml') workelements =[] lNodesWithLevel1 = xmlDoc.getElementsByTagName('wd:ID') for mynodes in lNodesWithLevel1: if mynodes.firstChild.nodeValue == 'WORK': workelements.append(mynodes) lNodesWithLevel2 = [lNode for lNode in xmlDoc.getElementsByTagName('wd:Email_Address_Data') if lNode.getElementsByTagName('wd:ID') == li]
解决方案
方法一:改进minidom代码
通过DOM元素的parentNode属性向上遍历,找到对应的Email_Address_Data元素,再提取邮箱地址:
from xml.dom import minidom xmlDoc = minidom.parse('XML_Example.xml') work_emails = [] # 遍历所有符合条件的ID元素 for id_node in xmlDoc.getElementsByTagName('wd:ID'): # 检查是否是WORK类型的Communication_Usage_Type_ID if id_node.getAttribute('wd:type') == 'Communication_Usage_Type_ID' and id_node.firstChild.nodeValue == 'WORK': # 向上遍历父节点,找到Email_Address_Data current_node = id_node while current_node and current_node.tagName != 'wd:Email_Address_Data': current_node = current_node.parentNode if current_node: # 提取邮箱地址 email_node = current_node.getElementsByTagName('wd:Email_Address')[0] work_emails.append(email_node.firstChild.nodeValue) print(work_emails) # 输出: ['jsmith@something.com']
方法二:使用lxml库(更简便)
lxml支持XPath查询,能直接定位到符合条件的邮箱元素,代码更简洁:
首先安装lxml:
pip install lxml
然后编写代码:
from lxml import etree # 定义命名空间 ns = { 'env': 'http://schema.xmlsoap.org/soap/envelope/', 'wd': 'urn:com.workway/bsvc' } tree = etree.parse('XML_Example.xml') # 使用XPath直接筛选WORK类型的邮箱 work_emails = tree.xpath('//wd:Email_Address_Data[.//wd:ID[@wd:type="Communication_Usage_Type_ID" and text()="WORK"]]/wd:Email_Address/text()', namespaces=ns) print(work_emails) # 输出: ['jsmith@something.com']
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

