如何使用C#递归打印XML树属性与元素并修复代码输出异常
问题原因
代码运行无输出是因为存在以下核心错误:
- XML节点选择逻辑错误:XML结构中
<AUTHORS>是父容器,内部直接嵌套<AUTHOR>节点,<AUTHOR>节点下不存在<AUTHORS>子节点,doc.Descendants("AUTHOR").Elements("AUTHORS")的查询结果是空集合,没有任何数据可加载。 - 节点取值方式错误:
FIRSTNAME、LASTNAME是<AUTHOR>的子元素,不是节点属性,用Attribute()方法取值会触发空引用异常。 - 模型定义缺失:需求要求存储的
id、obs、responsible三个属性没有在Author类中定义,不满足存储要求。 - 方法调用与作用域错误:
PrintAutors是实例方法,既没有在程序入口Main中被调用,方法内部也无法访问Main中定义的局部变量authors。 - 空值处理缺失:部分
<AUTHOR>节点没有responsible属性,直接取Value会抛异常;Children集合为空时调用无种子值的Aggregate方法,也会抛出序列无元素的错误。
修正后实现
第一步:补全Author模型类
新增需要存储的三个属性,同时优化ToString方法的空值兼容逻辑:
public class Author { public string Id { get; set; } public string Obs { get; set; } // responsible为可空属性,部分节点无该值 public string? Responsible { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public List<Author> Children { get; set; } = new(); public override string ToString() { var baseInfo = $"ID: {Id}, OBS: {Obs}, Responsible: {Responsible ?? "无"}, 姓名: {FirstName} {LastName}"; if (Children.Any()) { var childInfo = string.Join("\n ", Children.Select(c => c.ToString())); baseInfo += $"\n 子作者:\n {childInfo}"; } return baseInfo; } }
第二步:修正XML加载与打印逻辑
调整节点查询路径,区分属性和子元素的取值方式,补充空值保护,直接在入口调用打印逻辑:
using System.Xml.Linq; class Solution { public static string xmlFilePath = "authors.xml"; public static void Main() { XDocument doc = XDocument.Load(xmlFilePath); // 正确查询路径:先取根级AUTHORS节点,再查询其下所有AUTHOR直接子节点 var authorElements = doc.Element("AUTHORS")?.Elements("AUTHOR") ?? Enumerable.Empty<XElement>(); List<Author> authors = LoadAuthors(authorElements); // 遍历打印所有作者信息 foreach (var author in authors) { Console.WriteLine(author.ToString()); Console.WriteLine("------------------------"); } } public static List<Author> LoadAuthors(IEnumerable<XElement> authorElements) { return authorElements.Select(x => new Author() { // 读取节点属性值 Id = x.Attribute("id")?.Value ?? string.Empty, Obs = x.Attribute("obs")?.Value ?? string.Empty, Responsible = x.Attribute("responsible")?.Value, // 读取子元素值 FirstName = x.Element("FIRSTNAME")?.Value ?? string.Empty, LastName = x.Element("LASTNAME")?.Value ?? string.Empty, // 保留嵌套作者加载逻辑,兼容后续XML结构扩展 Children = LoadAuthors(x.Elements("AUTHORS").Elements("AUTHOR")) }).ToList(); } }
运行效果
程序启动后控制台会输出每个作者的完整信息,示例输出如下:
ID: _03131488, OBS: 0, Responsible: 1, 姓名: Dickson Richard ------------------------ ID: _03135122, OBS: 0, Responsible: 无, 姓名: Ancelotti Carlo ------------------------ ID: _0312C456, OBS: 0, Responsible: 1, 姓名: Howard Patricia ------------------------
内容的提问来源于stack exchange,提问作者Houndour99
相关产品推荐
相关产品推荐

