【问题标题】:Python XML parsing with ElementTree returns None使用 ElementTree 解析 Python XML 返回无
【发布时间】:2015-07-24 14:35:12
【问题描述】:

我正在尝试在 Python 中使用 ElementTree 解析这个 xml 字符串,

存储为字符串的数据,

xml = '''<?xml version="1.0" encoding="utf-8"?>
<SearchResults xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Student>
    <RollNumber>1</RollNumber>
    <Name>Abel</Name>
    <PhoneNumber>Not Included</PhoneNumber>
    <Email>abel@hisschool.edu</Email>
    <Grade>7</Grade>
</Student>
<Student>
    <RollNumber>2</RollNumber>
    <Name>Joseph</Name>
    <PhoneNumber>Not Included</PhoneNumber>
    <Email>joseph@hisschool.edu</Email>
    <Grade>7</Grade>
</Student>
<Student>
    <RollNumber>3</RollNumber>
    <Name>Mike</Name>
    <PhoneNumber>Not Included</PhoneNumber>
    <Email>mike@hisschool.edu</Email>
    <Grade>7</Grade>
</Student>
</SearchResults>'''

我用来将这个字符串解析为xml的代码,

from xml.etree import ElementTree

xml = ElementTree.fromstring(xml)

results = xml.findall('Student')

for students in results:
    for student in students:
        print student.get('Name')

print results 将结果打印为元素,

[<Element 'Student' at 0x7feb615b4ad0>, <Element 'Student' at 0x7feb615b4c50>, <Element 'Student' at 0x7feb615b4e10>]

在 for 循环中,print students 打印出相同的内容,

<Element 'Student' at 0x7fd722d88ad0>
<Element 'Student' at 0x7fd722d88c50>
<Element 'Student' at 0x7fd722d88e10>

无论如何,当我尝试使用 print student.get('Name') 获取学生的姓名时,程序返回 None。

我要做的是从每个标签的 xml 中提取值并构造一个字典。

【问题讨论】:

    标签: python xml elementtree


    【解决方案1】:

    这里有一个双循环:

    for students in results:
        for student in students:
            print student.get('Name')
    

    students一个&lt;Student&gt; 元素。通过迭代,您将获得包含在该元素中的单个元素。那些包含的元素(&lt;RollNumber&gt;&lt;Name&gt; 等)没有Name 属性。

    .get() 方法仅访问属性,但您似乎想要获取 &lt;Name&gt; 元素。在此处使用 .find() 或 XPath 表达式:

    for student in results:
        name = student.find('Name')
        if name is not None:
            print name.text
    

    for student_name in xml.findall('.//Student/Name'):
        print name.text
    

    【讨论】:

      【解决方案2】:

      如果您不熟悉 XML 处理:

      • lxml 是一个快速而强大的库,用于在 python 中与 XML 进行交互。标准库没有完整的xpath 支持。
      • xpath 是一种用于检查 XML 文档的查询语言,它有一个陡峭的学习曲线,但很容易在 StackOverflow 上获得帮助。 xpath 非常有用,以至于我在使用 API 时开始将 JSON 转换为 XML,这样我就可以编写 xpath 查询而不是疯狂的嵌套字典解引用。

      from lxml import etree
      from pprint import pprint
      
      doc = etree.XML('''<?xml version="1.0" encoding="utf-8"?>
      <SearchResults xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Student>
          <RollNumber>1</RollNumber>
          <Name>Abel</Name>
          <PhoneNumber>Not Included</PhoneNumber>
          <Email>abel@hisschool.edu</Email>
          <Grade>7</Grade>
      </Student>
      <Student>
          <RollNumber>2</RollNumber>
          <Name>Joseph</Name>
          <PhoneNumber>Not Included</PhoneNumber>
          <Email>joseph@hisschool.edu</Email>
          <Grade>7</Grade>
      </Student>
      <Student>
          <RollNumber>3</RollNumber>
          <Name>Mike</Name>
          <PhoneNumber>Not Included</PhoneNumber>
          <Email>mike@hisschool.edu</Email>
          <Grade>7</Grade>
      </Student>
      </SearchResults>''')
      
      def first(seq,default=None):
        for item in seq:
          return item
        return default
      
      def simple_children_to_dict(element):
        result = {}
        for child in element:
          result[child.tag] = child.text
        return result
      
      def get_by_rollnumber(number,search_results):
        student_element = first(search_results.xpath('Student[./RollNumber=$number]',number=number))
        if student_element is None:
          raise Exception("Student Number {0} not found".format(number))
        return simple_children_to_dict(student_element)  
      
      def get_all_students(search_results):
        students = []
        for student_element in doc.xpath('Student'):
          students.append(simple_children_to_dict(student_element))
        return students
      

      然后:

      >>> pprint(get_by_rollnumber(2,doc))
      {'Email': 'joseph@hisschool.edu',
       'Grade': '7',
       'Name': 'Joseph',
       'PhoneNumber': 'Not Included',
       'RollNumber': '2'}
      >>>
      >>> pprint(get_all_students(doc))
      [{'Email': 'abel@hisschool.edu',
        'Grade': '7',
        'Name': 'Abel',
        'PhoneNumber': 'Not Included',
        'RollNumber': '1'},
       {'Email': 'joseph@hisschool.edu',
        'Grade': '7',
        'Name': 'Joseph',
        'PhoneNumber': 'Not Included',
        'RollNumber': '2'},
       {'Email': 'mike@hisschool.edu',
        'Grade': '7',
        'Name': 'Mike',
        'PhoneNumber': 'Not Included',
        'RollNumber': '3'}]
      

      细微之处:

      • xpath 查询通常会返回一个结果集,因为大多数查询可能有多个匹配项。因此使用了一个帮助器first 函数。

      【讨论】:

        猜你喜欢
        • 2021-02-06
        • 2017-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-16
        • 1970-01-01
        相关资源
        最近更新 更多