【问题标题】:Extract XML tag data based on attributes of a different tag根据不同标签的属性提取 XML 标签数据
【发布时间】:2018-04-11 16:15:51
【问题描述】:

我正在使用 xml.etree 来解析一些需要使用 Python 导入数据库的巨大 XML 文件,但由于某种原因,我无法弄清楚如何根据属性提取特定标签不同的标签

例如,在下面包含的这段 XML 中,我需要提取 NicamWarningCS 标签下的标签文本,并将它们放在一个列表中。关于如何实现这一目标的任何建议?

<Main xmlns:mpeg7="urn:mpeg:mpeg7:schema:2001" xmlns="urn:tva:metadata:2004">
  <ProgramDescription>
    <ProgramInformationTable>
      <ProgramInformation programId="123456">
        <BasicDescription>
           <Genre href="urn:tva:metadata:cs:2004:2.4">
             <Name xml:lang="NL"><![CDATA[Film]]></Name>
           </Genre>
           <Genre href="urn:po:metadata:cs:GenreCS:2009:4" type="other">
             <Name xml:lang="NL"><![CDATA[Film]]></Name>
           </Genre>
           <Genre href="urn:po:metadata:cs:NicamWarningCS:2007:t">
             <Name xml:lang="NL"><![CDATA[Grof taalgebruik]]></Name>
           </Genre>
           <Genre href="urn:po:metadata:cs:NicamWarningCS:2007:g">
             <Name xml:lang="NL"><![CDATA[Geweld]]></Name>
           </Genre>
           <Genre href="urn:po:metadata:cs:GenreCS:2009:23" type="other">
             <Name xml:lang="NL"><![CDATA[Biography/Drama/History]]></Name>
           </Genre>
         </BasicDescription>
       </ProgramInformation>
     </ProgramInformationTable>
   </ProgramDescription>
 </Main>

【问题讨论】:

    标签: python xml


    【解决方案1】:

    这是我要做的详细过程:

    import xml.etree.ElementTree as ET
    
    # 1. Parse your xml file
    tree = ET.parse('your.xml')
    
    # 2. Get the root
    root = tree.getroot()
    
    # 3. Set the tag and attribute you are looking for
    ns = 'urn:tva:metadata:2004'
    matchTag = 'NicamWarningCS'
    
    # 4. retrieve all Genres
    genres = root.find('{%s}ProgramDescription' % ns) \
        .find('{%s}ProgramInformationTable' % ns) \
        .find('{%s}ProgramInformation' % ns) \
        .find('{%s}BasicDescription' % ns) \
        .findall('{%s}Genre' % ns)
    
    # 5. filter them in order to get just the Names of the ones that match your matchTag : 'NicamWarningCS'
    filteredGenreNames = [genre.find('{%s}Name' % ns) for genre in genres if matchTag in genre.get('href')]
    
    # 6. extract the text of the tags
    data = [t.text for t in filteredGenreNames]
    
    print(data)
    # ['Grof taalgebruik', 'Geweld']
    

    【讨论】:

    • 我认为这个答案比我找到的解决方案更具可读性,并且很好地展示了 Erik 提出的解决方案。谢谢!
    【解决方案2】:

    只需获取所有 Genre 元素并过滤具有您感兴趣的 href 属性的元素:

    ns = 'urn:tva:metadata:2004'
    all_genres = fromstring(xml) \
        .find('{%s}ProgramDescription' % ns) \
        .find('{%s}ProgramInformationTable' % ns) \
        .find('{%s}ProgramInformation' % ns) \
        .find('{%s}BasicDescription' % ns) \
        .findall('{%s}Genre' % ns)
    some_genres = [g for g in all_genres if 'NicamWarningCS' in g.get('href')]
    

    【讨论】:

      【解决方案3】:

      我无法快速启动并运行 Erik 的答案,但它向我暗示了另一种解决方案的方向,该解决方案能够解决我的问题。

      通过创建一个包含所有类型的字典,我能够过滤掉所有 Nicam 警告并将它们添加到一个列表中,然后我可以使用该列表来填充我的 SQL 语句:

      genreitemdict = dict()
      for genreitem in program.iter("{urn:tva:metadata:2004}Genre"):
          for child in genreitem:
              genreitemdict[genreitem.attrib['href']] = child.text
              NicamWarningCS = [v for k, v in genreitemdict.items() if 'NicamWarningCS' in k]
      print NicamWarningCS
      

      这可能不是最好的解决方案,但现在就可以了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 2012-05-28
        • 1970-01-01
        相关资源
        最近更新 更多