You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正XmlReader类实现XML到动态对象的递归解析?

实现XmlReader类递归解析XML为动态对象

需求说明

请完成XmlReader类,该类的构造函数接收XML文档字符串,将其转换为动态对象:

  • XML节点可作为对象的属性直接访问
  • 节点对应的XML内容可通过text属性获取
  • 必须支持任意层级XML的递归解析

示例XML字符串

xml_string = "<note> <to>Tove</to>    <from>Jani</from>    <heading>Reminder</heading>    <body>Don't forget me this weekend!</body>  </note>  "

用户的错误实现代码

import xml.etree.ElementTree as ET

class XmlReader:
    def __init__(self, xml=None):
        self.text = ""
        if xml is not None:
            doc = ET.fromstring(xml)
            self.text = ET.tostring(doc).decode('ascii')
            xml = XmlReader()
            xml.text = doc.text
            setattr(self, doc.tag, xml)
            
xml_string = \
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + \
                    "<note>" + \
                      "<to>Tove</to>" +\
                      "<from>Jani</from>" + \
                      "<heading>Reminder</heading>" + \
                      "<body>Don't forget me this weekend!</body>" +\
                    "</note>"
                    
xmlObj = XmlReader(xml_string)
print(xmlObj.text)
print(xmlObj.note.text)
print(xmlObj.note.to.text)

预期输出

"<note> <to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"

"<to>Tove</to>"

"<from>Jani</from>"

实际错误输出

<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>
None
Traceback (most recent call last):
    print(xmlObj.note.to.text)
AttributeError: 'XmlReader' object has no attribute 'to'

问题分析与修正方案

错误原因

  1. 未递归处理子节点:原代码仅创建了根节点的XmlReader实例,完全没有处理根节点下的子元素(如to、from等),导致无法访问子节点属性。
  2. doc.text理解错误:doc.text获取的是当前节点内部的空白文本(比如<note>和第一个子节点<to>之间的空白),而非子节点对应的XML字符串,所以输出None。

正确实现代码

修改XmlReader类,使其递归遍历所有子元素,同时处理Python关键字作为标签名的情况,避免语法错误:

import xml.etree.ElementTree as ET
import keyword

class XmlReader:
    def __init__(self, xml_or_element=None):
        self.text = ""
        if xml_or_element is None:
            return
        
        # 兼容传入XML字符串或Element对象
        if isinstance(xml_or_element, str):
            element = ET.fromstring(xml_or_element)
        else:
            element = xml_or_element
        
        # 保存当前节点的XML内容到text属性
        self.text = ET.tostring(element, encoding='unicode')
        
        # 递归处理所有子节点,创建对应的XmlReader实例并设置为属性
        for child in element:
            # 处理Python关键字作为标签名的情况(如from改为from_)
            attr_name = child.tag if not keyword.iskeyword(child.tag) else f"{child.tag}_"
            child_reader = XmlReader(child)
            setattr(self, attr_name, child_reader)

# 测试代码
xml_string = \
        "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + \
                    "<note>" + \
                      "<to>Tove</to>" +\
                      "<from>Jani</from>" + \
                      "<heading>Reminder</heading>" + \
                      "<body>Don't forget me this weekend!</body>" +\
                    "</note>"
                    
xmlObj = XmlReader(xml_string)
# 输出带引号的结果,匹配预期格式
print(f'"{xmlObj.text.strip()}"')
print(f'"{xmlObj.note.to.text.strip()}"')
print(f'"{xmlObj.note.from_.text.strip()}"')

输出结果

"<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"
"<to>Tove</to>"
"<from>Jani</from>"

内容的提问来源于stack exchange,提问作者Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 07:20:00