【问题标题】:Using Python 3.6 to parse XML how can I determine if an XML tag contains no data使用 Python 3.6 解析 XML 如何确定 XML 标记是否不包含数据
【发布时间】:2017-02-09 07:55:53
【问题描述】:

我正在尝试通过编写一个脚本来学习 Python,该脚本将从 XML 文件中的多个记录中提取数据。通过在网络上搜索,我已经能够找到大多数问题的答案,但是我还没有找到一种方法来确定 XML 标记在 getElementsByTagName("tagname") 之前是否不包含任何数据[0].firstChild.data 方法被使用,当没有数据存在时抛出 AttributeError。我意识到我可以尝试编写代码并处理 AttributeError,但我宁愿在尝试提取数据之前知道标签是空的,而不必处理异常。 下面是一个 XML 文件的示例,其中包含两条记录,一条带有标签中的数据,一条带有空标签。

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<records>
  <rec>
    <name>ZYSRQPO</name>
    <state>Washington</state>
    <country>United States</country>
  </rec>
  <rec>
    <name>ZYXWVUT</name>
    <state></state>
    <country>Mexico</country>
  </rec>
</records>

这是我可能用来提取数据的代码示例:

from xml.dom import minidom
import sys

mydoc  = minidom.parse('mydataFile.xml')
records = mydoc.getElementsByTagName("rec")

for rec in records:
    try:
        name = rec.getElementsByTagName("name")[0].firstChild.data
        state = rec.getElementsByTagName("state")[0].firstChild.data
        country = rec.getElementsByTagName("country")[0].firstChild.data
        print('{}\t{}\t{}'.format(name, state, country))

    except (AttributeError):
        print('AttributeError encountered in record {}'.format(name), file=sys.stderr)
        continue

处理此文件时,不会打印名为 ZYXWVUT 的记录的任何信息,除非遇到异常。我希望能够为使用的州名设置一个空值,并打印有关此记录的其余信息。有没有一种方法可以用来做我想做的事情,这样我就可以在使用getElementsByTagName之前使用if语句来确定标签是否不包含数据并在找不到数据时遇到错误?

【问题讨论】:

    标签: xml-parsing minidom python-3.6


    【解决方案1】:
    from xml.dom import minidom
    import sys
    
    mydoc  = minidom.parse('mydataFile.xml')
    records = mydoc.getElementsByTagName("rec")
    
    for rec in records:
        name = rec.getElementsByTagName("name")[0].firstChild.data
        state = None if len(rec.getElementsByTagName("state")[0].childNodes) == 0 else rec.getElementsByTagName("state")[0].firstChild.data
        country = rec.getElementsByTagName("country")[0].firstChild.data
        print('{}\t{}\t{}'.format(name, state, country))
    

    或者如果有任何机会,那个名字和国家也是空的:

    from xml.dom import minidom
    import sys
    
    
    def get_node_data(node):
        if len(node.childNodes) == 0:
            result = None
        else:
            result = node.firstChild.data
        return result
    
    
    mydoc  = minidom.parse('mydataFile.xml')
    records = mydoc.getElementsByTagName("rec")
    
    for rec in records:
        name = get_node_data(rec.getElementsByTagName("name")[0])
        state = get_node_data(rec.getElementsByTagName("state")[0])
        country = get_node_data(rec.getElementsByTagName("country")[0])
        print('{}\t{}\t{}'.format(name, state, country))
    

    【讨论】:

    • 谢谢,感谢您的回复。我特别喜欢第二个建议,尽管名称或国家/地区几乎不可能为空,但它使结构看起来更优雅。我现在还有其他地方需要去,所以我没有尝试过,但我会尽快尝试。
    【解决方案2】:

    我尝试了 reedcourty 的第二个建议,发现效果很好。但我决定,如果元素为空,我真的不希望返回 none。这是我想出的:

    from xml.dom import minidom
    import sys
    
    def get_node_data(node):
        if len(node.childNodes) == 0:
            result = '*->No ' + node.nodeName + '<-*'
        else:
            result = node.firstChild.data
        return result
    
    mydoc  = minidom.parse(dataFileSpec)
    records = mydoc.getElementsByTagName("rec")
    
    for rec in records:
        name = get_node_data(rec.getElementsByTagName("name")[0])
        state = get_node_data(rec.getElementsByTagName("state")[0])
        country = get_node_data(rec.getElementsByTagName("country")[0])
        print('{}\t{}\t{}'.format(name, state, country))
    

    当对这个 XML 运行时:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <records>
      <rec>
        <name>ZYSRQPO</name>
        <country>United States</country>
        <state>Washington</state>
      </rec>
      <rec>
        <name></name>
        <country>United States</country>
        <state>Washington</state>
      </rec>
      <rec>
        <name>ZYXWVUT</name>
        <country>Mexico</country>
        <state></state>
      </rec>
      <rec>
        <name>ZYNMLKJ</name>
        <country></country>
        <state>Washington</state>
      </rec>
    </records>
    

    它产生这个输出:

    ZYSRQPO Washington      United States
    *->No name<-*   Washington      United States
    ZYXWVUT *->No state<-*  Mexico
    ZYNMLKJ Washington      *->No country<-*
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多