我无法使用python正确循环遍历xml文件,如何循环遍历并以正确的顺序返回多个不同的标记?

2024-09-30 04:39:13 发布

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

我有一个XML文件,我需要从中返回各种标记的文本,CompanyName、FirstName、LastName、Content、Time等

到目前为止,我可以使用for-each循环返回其中一个标记的每个iterance的文本,也可以返回所有需要的数据,但以连续块的形式返回

我正在努力寻找答案的是,如何按照XML文档中指定标记的正确时间顺序返回相应的文本

下面我将描述我已经尝试过的

首先,这里是我正在解析的XML内容:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<FileDump>
<Version>1.3</Version>
<Conversation>
<RoomID>1</RoomID>
<StartTime>09/09/2021 19:35:35</StartTime>
<StartTimeUTC>1631216135</StartTimeUTC>
<ParticipantEntered>
<User>
<LoginName>JJohnson</LoginName>
<FirstName>John</FirstName>
<LastName>Johnson</LastName>
<CompanyName>ABC LimitedCO</CompanyName>
<EmailAddress>JJ@ABC.com</EmailAddress>
<CorporateEmailAddress>none</CorporateEmailAddress>
<Content> good Morning how are you today? </Content>
</User>
<DateTime>09/09/2021 19:35:35</DateTime>
<DateTimeUTC>1631216135</DateTimeUTC>
<ConversationID></ConversationID>
</ParticipantEntered>
<Message>
<User>
<LoginName>MMArks</LoginName>
<FirstName>Mark</FirstName>
<LastName>Marks</LastName>
<CompanyName>XYZ Corp</CompanyName>
<EmailAddress>mm@xyz.com</EmailAddress>
<CorporateEmailAddress></CorporateEmailAddress>
<Content> what time is it? </Content>
</User>
</Message>
</Conversation>
</FileDump>

以下代码块是我迄今为止尝试过的

import xml.etree.ElementTree as ET
mytree = ET.parse(r'sample.xml')
myroot = mytree.getroot()


for content in myroot.iter('Content'):
    for name in myroot.iter('CompanyName'):
        cname = name
    output = content
    print(name.text, output.text)

#此脚本将返回:

早上好,今天好吗? XYZ公司现在几点了

首先应该说ABC有限公司

#然后我尝试了以下方法:

for content in myroot.findall('Conversation'):
     output = content.find('Content')
     FName = content.find('FirstName')
     LName = content.find('LastName')
     cont = content.find('CompanyName')
     print(cont, "\n", FName, LName, output)

#这又回来了

没有 无无无

因此它不会触发错误,但当我要求在以下范围内返回文本时:

for content in myroot.findall('Conversation'):
     output = content.find('Content').text
     FName = content.find('FirstName').text
     LName = content.find('LastName').text
     cont = content.find('CompanyName').text
     print(cont, "\n", FName, LName, output)

#这会返回一个错误“'NoneType'对象没有属性'text'”-即使有明显的文本,我也不明白它为什么会失败

#但奇怪的是,当我使用从ElementTree文档中获得的以下XML脚本时,上面的代码块完全按照我的要求工作,我对该脚本进行了编辑,以添加我在真实脚本中寻找的标记,不起作用的XML代码已被验证为正确的XML,因此我排除了其中的任何错误-我对XML了解不够,无法发现差异并理解其不起作用的原因:

(与最后一个代码块组合时,此选项有效:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
        <FirstName>John</FirstName>
        <LastName>Johnson</LastName>
        <CompanyName>ABC LIMITED</CompanyName>
        <Content>
       Good Morning How are you?
        </Content>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
        <FirstName>Mark</FirstName>
        <LastName>Marks</LastName>
        <CompanyName>XYZ Corp</CompanyName>
        <Content>
        Good Morning
        </Content>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
        <FirstName>Keith</FirstName>
        <LastName>Keitherson</LastName>
        <CompanyName>WW Corp</CompanyName>
        <Content>
     Good Evening 
        </Content>
    </country>
</data>

并返回以下结果:

ABC有限公司 约翰·约翰逊 早上好,你好吗

XYZ公司 标记 早上好

WW公司 基思·基瑟森 晚上好

我尝试过的其他事情包括:

for content in myroot.itertext():
    print(content)

#这确实会返回文档中所有可用的文本,但不需要争论来缩小我对所需标签的搜索范围

正如你可能知道的那样,我是一个编码高手,我正在努力解决出现的问题

我毫不怀疑,这是一个非常简单和基本的改变,我需要作出,但由于我缺乏知识,加上大量不同的方式,这可以在网上完成,我已经困惑自己,现在发现自己在这里

我已经尽力提供尽可能多的信息,所以任何知道的人都应该能够为我指出正确的方向

如果需要更多信息,请告诉我

编辑:

所需的输出如下:

ABC有限公司 约翰·约翰逊 早上好,今天好吗

XYZ公司 标记 现在几点了

根据第一条建议,我现在使用的最新脚本是:

for content in myroot.findall('.//Conversation'):
     output = content.find('.//Content').text
     FName = content.find('.//FirstName').text
     LName = content.find('.//LastName').text
     cont = content.find('.//CompanyName').text
     print(cont, "\n", FName, LName, output)

这只返回指定标记的一个(第一个)结果,如下所示:

ABC有限公司 约翰·约翰逊早上好,你今天好吗

编辑:

我的成功与我收到的答案不尽相同,建议在这段XML上无法完美运行:

<?xml version="1.0" encoding="UTF-8"?>

<FileDump>
<Version>1.3</Version>
<Conversation>
<RoomID>CHAT</RoomID>
<StartTime>09/09/2021 19:35:35</StartTime>
<StartTimeUTC>1631216135</StartTimeUTC>
<ParticipantEntered InteractionType="N" DeviceType="M">
<User>
<LoginName>JJohnson</LoginName>
<FirstName>JOHN</FirstName>
<LastName>Johnson</LastName>
<CompanyName>ABC Limited CO</CompanyName>
<EmailAddress>JJ@abc.com</EmailAddress>
<CorporateEmailAddress></CorporateEmailAddress>
</User>
<DateTime>09/09/2021 19:35:35</DateTime>
<DateTimeUTC>1631216135</DateTimeUTC>
<Content>
Testing Content 1 
</Content>
<ConversationID>CHAT</ConversationID>
</ParticipantEntered>
<Message>
<User>
<LoginName>MMarks</LoginName>
<FirstName>Mark</FirstName>
<LastName>MArks</LastName>
<CompanyName>XYZ Corp</CompanyName>
<EmailAddress></EmailAddress>
<CorporateEmailAddress></CorporateEmailAddress>
</User>
<DateTime>09/09/2021 19:35:35</DateTime>
<DateTimeUTC>1631216135</DateTimeUTC>
<Content>
Testing content 2
</Content>
<ConversationID>CHAT</ConversationID>
</Message>
<ParticipantEntered>
<User>
<LoginName>SSamson</LoginName>
<FirstName>Sam</FirstName>
<LastName>Samson</LastName>
<CompanyName>123 CorpCO</CompanyName>
<EmailAddress></EmailAddress>
<CorporateEmailAddress></CorporateEmailAddress>
<Content>
Testing content 3
</Content>
</User>
</ParticipantEntered>
</Conversation>
</FileDump>

这将返回:

ABC有限公司Johnson JOHN未找到 未找到XYZ公司标记 123 CorpCO Samson Sam 测试内容3


Tags: textname标记xmlcontentfindfirstnameabc
1条回答
网友
1楼 · 发布于 2024-09-30 04:39:13

看起来下面这张照片就是你要找的

import xml.etree.ElementTree as ET

xml = '''<?xml version="1.0" encoding="UTF-8"?>
<FileDump>
   <Version>1.3</Version>
   <Conversation>
      <RoomID>CHAT</RoomID>
      <StartTime>09/09/2021 19:35:35</StartTime>
      <StartTimeUTC>1631216135</StartTimeUTC>
      <ParticipantEntered InteractionType="N" DeviceType="M">
         <User>
            <LoginName>JJohnson</LoginName>
            <FirstName>JOHN</FirstName>
            <LastName>Johnson</LastName>
            <CompanyName>ABC Limited CO</CompanyName>
            <EmailAddress>JJ@abc.com</EmailAddress>
            <CorporateEmailAddress />
         </User>
         <DateTime>09/09/2021 19:35:35</DateTime>
         <DateTimeUTC>1631216135</DateTimeUTC>
         <Content>Testing Content 1</Content>
         <ConversationID>CHAT</ConversationID>
      </ParticipantEntered>
      <Message>
         <User>
            <LoginName>MMarks</LoginName>
            <FirstName>Mark</FirstName>
            <LastName>MArks</LastName>
            <CompanyName>XYZ Corp</CompanyName>
            <EmailAddress />
            <CorporateEmailAddress />
         </User>
         <DateTime>09/09/2021 19:35:35</DateTime>
         <DateTimeUTC>1631216135</DateTimeUTC>
         <Content>Testing content 2</Content>
         <ConversationID>CHAT</ConversationID>
      </Message>
      <ParticipantEntered>
         <User>
            <LoginName>SSamson</LoginName>
            <FirstName>Sam</FirstName>
            <LastName>Samson</LastName>
            <CompanyName>123 CorpCO</CompanyName>
            <EmailAddress />
            <CorporateEmailAddress />
            <Content>Testing content 3</Content>
         </User>
      </ParticipantEntered>
   </Conversation>
</FileDump>
'''

NOT_FOUND = '__NOT_FOUND__'


def _get(ele, name):
    sub = ele.find(name)
    return sub.text if sub is not None else NOT_FOUND


root = ET.fromstring(xml)
elements = ['CompanyName', 'LoginName', 'FirstName', 'Content']


def loop(base_ele):
    for pe in root.findall(f'.//{base_ele}'):
        content = _get(pe, 'Content')
        u = pe.find('User')
        data = [_get(u, x) for x in elements] if content == NOT_FOUND else [_get(u, x) for x in elements[:-1]]
        if len(data) < 4:
            data.append(content)
        msg = ' '.join(data)
        print(f"{msg}")


loop('ParticipantEntered')
loop('Message')

输出

ABC Limited CO JJohnson JOHN Testing Content 1
123 CorpCO SSamson Sam Testing content 3
XYZ Corp MMarks Mark Testing content 2

相关问题 更多 >

    热门问题