使用Python 3.6解析XML如何确定XML标记是否不包含数据

时间:2017-02-09 07:55:53

标签: xml-parsing minidom python-3.6

我正在尝试通过编写一个脚本来学习Python,该脚本将从XML文件中的多个记录中提取数据。我已经能够通过在网上搜索找到我的大部分问题的答案,但我还没有找到一种方法来确定XML标签是否在getElementsByTagName之前不包含任何数据(" 标记名")[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的记录的信息。我希望能够使用所使用的州名称的空值以及有关此记录的其他信息。有没有一种方法可以用来做我想要的,所以我可以使用if语句来判断标签在使用getElementsByTagName之前是否包含数据,并且在没有找到数据时遇到错误?

2 个答案:

答案 0 :(得分: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))

答案 1 :(得分:0)

我尝试了reedcourty的第二个建议,发现它很有效。但我决定,如果元素为空,我真的不希望没有返回。以下是我提出的建议:

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<-*