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

I am failing to correctly loop through an xml file with python, how can I loop through and return multiple different tags in the correct order?

我有一个 XML 文件,我需要从中 return 来自各种标签、公司名称、名字、姓氏、内容、时间等的文本

到目前为止,我可以 return 使用 for each 循环的其中一个标签的每次迭代的文本,或者我可以 return 所有必需的数据,但在连续的块中。

我一直在努力寻找答案的是,如何 return 指定标签中的适当文本以正确的时间顺序出现在 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)

#这个脚本将return:

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

第一个应该说 ABC Limited

#然后我试了这个:

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)

#这个returns

None None None None

所以它不会触发错误,但是当我询问 return 中的文本时:

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)

#这 return 是一个错误“'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>

它 return 的结果如下:

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

XYZ 公司 标记标记 早上好

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

我尝试过的其他事情是:

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

#这会 return 文档中的所有可用文本,但不会争论以缩小我对所需标签的搜索范围

你可能会说我是一个编码菜鸟,我正在努力解决这个问题。

我毫不怀疑我需要做的是一个非常简单和基本的改变,但是由于我缺乏知识,再加上可以在线完成的大量不同方法,我感到困惑,现在我发现我在这里。

我已尽力提供尽可能多的信息,因此知情人士应该能够为我指明正确的方向。

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

编辑:

期望的输出如下:

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)

这 return 只是一个(第一个)来自指定标签的结果:

ABC LimitedCO 约翰·约翰逊早上好你今天好吗?

编辑:

我收到的答案喜忧参半,建议在 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>

这个returns:

ABC 有限公司 CO Johnson JOHN not_found XYZ 公司 MArks 标记 not_found 死神123 测试内容3

看起来下面就是您要查找的内容

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