如何修正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'
问题分析与修正方案
错误原因
- 未递归处理子节点:原代码仅创建了根节点的XmlReader实例,完全没有处理根节点下的子元素(如
to、from等),导致无法访问子节点属性。 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
相关产品推荐
相关产品推荐

