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

XmlReader不移动游标取值及读取XML到List<LogData>的问题

解决XmlReader读取值不移动游标及填充List的问题

我来帮你搞定这两个问题——先说说你遇到reader.Value为空和ReadString()移动游标导致跳过节点的原因,再给你完整的代码示例把XML数据读到List<LogData>集合里。

问题原因解析

  1. reader.Value为空:XmlReader的Value属性只有在当前节点是文本节点、CDATA节点、属性节点这类有内容的节点时才会有值。如果你的游标停留在<Id>这种元素标签节点上,Value自然是空的。
  2. ReadString()移动游标:这个方法会从当前位置读取所有连续文本,然后直接把游标移到文本之后的节点,这就会打乱你后续的节点遍历逻辑,导致跳过原本要处理的内容。

不移动原游标读取值的方法

如果不想影响原XmlReader的游标位置,推荐用ReadSubtree()方法。它会创建一个独立的子阅读器,只负责处理当前元素及其子节点,操作这个子阅读器完全不会干扰原阅读器的位置。当你用完子阅读器并关闭后,原阅读器会自动回到当前元素的结束标签位置,不会打乱整体遍历流程。

完整读取XML到List的示例

首先我们先定义LogData类(假设你的日志数据包含Id、Message、Time三个字段,你可以根据实际XML结构调整):

public class LogData
{
    public int Id { get; set; }
    public string Message { get; set; }
    public DateTime Time { get; set; }
}

然后是读取XML的核心代码,这里我们用XmlReader的标准遍历逻辑,结合子阅读器安全读取值:

using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;

namespace ReadXML
{
    class Program
    {
        private static string XML = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<Logs>
  <Log>
    <Id>1</Id>
    <Message>Database connection failed</Message>
    <Time>2024-05-20 09:30:00</Time>
  </Log>
  <Log>
    <Id>2</Id>
    <Message>File upload succeeded</Message>
    <Time>2024-05-20 09:45:00</Time>
  </Log>
</Logs>";

        static void Main(string[] args)
        {
            List<LogData> logDatas = new List<LogData>();

            // 用StringReader加载XML字符串
            using (StringReader stringReader = new StringReader(XML))
            using (XmlReader reader = XmlReader.Create(stringReader))
            {
                while (reader.Read())
                {
                    // 只处理<Log>元素节点
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "Log")
                    {
                        // 创建子阅读器处理当前<Log>的子节点,不影响原阅读器位置
                        using (XmlReader logReader = reader.ReadSubtree())
                        {
                            LogData log = new LogData();
                            while (logReader.Read())
                            {
                                // 读取<Log>下的子元素值
                                if (logReader.NodeType == XmlNodeType.Element)
                                {
                                    switch (logReader.Name)
                                    {
                                        case "Id":
                                            // 用ReadElementContentAsString读取值,自动移动到元素结束标签
                                            log.Id = int.Parse(logReader.ReadElementContentAsString());
                                            break;
                                        case "Message":
                                            log.Message = logReader.ReadElementContentAsString();
                                            break;
                                        case "Time":
                                            log.Time = DateTime.Parse(logReader.ReadElementContentAsString());
                                            break;
                                    }
                                }
                            }
                            logDatas.Add(log);
                        }
                    }
                }
            }

            // 验证读取结果
            foreach (var log in logDatas)
            {
                Console.WriteLine($"Id: {log.Id}, Message: {log.Message}, Time: {log.Time}");
            }
        }
    }
}

关键说明

  • 用ReadSubtree()处理单个<Log>节点,确保原阅读器的游标不会被打乱,避免跳过后续节点。
  • 使用ReadElementContentAsString()读取元素文本值,这个方法会自动从当前元素节点移动到结束标签,在子阅读器里操作完全不会影响原阅读器的遍历。
  • 遍历节点时先判断NodeType和Name,确保只处理我们需要的元素,避免无效操作。

另外,如果你的XML里有属性值(比如<Log id="1">),可以用reader.GetAttribute("id")来获取,这个方法不会移动游标,非常适合读取属性值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:18:47