【问题标题】:Why is XmlReader skipping tags?为什么 XmlReader 跳过标签?
【发布时间】:2019-01-19 10:44:18
【问题描述】:

XmlReader 正在跳过标签,我不知道为什么。如果你执行下面的代码,你会看到 ID 123 和 789 被打印出来,这意味着 456 被跳过了。如果您运行使用 1234 的替代内存流,您将看到仅打印 123 和 456 意味着 1234 和 789 被跳过。

这是主要部分。完整代码如下。我创建了一个带有流的 XML 阅读器,我有一个 while 循环,我检查我想要的深度(因为节点不在深度 0 处)。 XElement.ReadFrom(root) as XElement 根据我的理解读取 XML 直到标签关闭,这就是我想要的。然后我简单地打印出 id 值。很简单,不到10行代码

var root = XmlReader.Create(fs);
root.MoveToElement();
while (root.Read())
{
    if (root.NodeType == XmlNodeType.EndElement || root.Depth != 1)
        continue;
    var el = XElement.ReadFrom(root) as XElement;
    Console.WriteLine(el.Attribute("id").Value);
}

如果我在</node><node> 之间添加换行符,它不会跳过标签,但感觉就像是创可贴,我不确定我的输入是否会在</node> 之后有换行符。


using System.Xml.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace nearMe
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var fs = new MemoryStream(UTF8Encoding.UTF8.GetBytes(@"<?xml version=""1.0"" encoding=""utf-8""?><test><node id=""123"">
        <tag k=""amenity"" v=""fuel"" />
    </node><node id=""456"">
        <tag k=""name"" v=""B"" />
    </node><node id=""789"">
        <tag k=""amenity"" v=""test"" />
    </node></test>")))
            {
                var root = XmlReader.Create(fs);
                root.MoveToElement();

                while (root.Read())
                {
                    if (root.NodeType == XmlNodeType.EndElement || root.Depth != 1)
                        continue;
                    var el = XElement.ReadFrom(root) as XElement;
                    if (el == null)
                        continue;
                    if (el.Name != "node")
                        continue;

                    Console.WriteLine(el.Attribute("id").Value);
                }
            }
        }
    }
}

using (var fs = new MemoryStream(UTF8Encoding.UTF8.GetBytes(@"<?xml version=""1.0"" encoding=""utf-8""?>
    <test>
        <node id=""123"">
            <tag k=""amenity"" v=""fuel"" />
        </node>
        <node id=""1234"">
            <tag k=""amenity"" v=""fuel"" />
        </node>
        <node id=""456"">
            <tag k=""name"" v=""B"" />
        </node>
        <node id=""789"">
            <tag k=""amenity"" v=""test"" />
        </node>
    </test>"
)))

【问题讨论】:

  • 您可能已经注意到,每隔一个元素就会被跳过。除此之外,如果您知道节点名称,我建议您按名称读取节点。恕我直言,阅读更容易。
  • 您没有获得所有元素的原因是由于获得了第一个节点,然后您位于第二个节点,然后跳过第二个节点移动到下一个节点。我的解决方案检查你是否在一个节点上,所以你不要移动。

标签: c# .net xml xmlreader


【解决方案1】:

在类似问题的评论中指出了您的错误:

调用 [XElement.ReadFrom] 读取元素并转到下一个元素,然后以下 [root.Read()] 再次读取下一个元素。如果它们碰巧具有相同的名称并且是连续的,那么您基本上会错过一个元素。 (pbz)

解决此问题的最简单方法是删除 ReadFrom 并继续从阅读器获取值:

            while (root.Read())
            {
                if (root.NodeType != XmlNodeType.Element || 
                    root.Depth != 1 ||
                    root.Name != "node")
                    continue;

                Console.WriteLine(root.GetAttribute("id"));
            }

【讨论】:

    【解决方案2】:
    using (var fs = new FileStream("test.xml", FileMode.Open, FileAccess.Read))
    {
        var test = XElement.Load(fs);
        var nodes = test.XPathSelectElements("node[@id]");
    
        foreach (var node in nodes)
        {
            Console.WriteLine(node.Attribute("id").Value);
        }
    }
    

    【讨论】:

      【解决方案3】:

      使用下面的代码。它不会跳过并使用 xml 阅读器。

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Xml;
      using System.Xml.Linq;
      using System.IO;
      
      namespace ConsoleApplication1
      {
          class Program
          {
              static void Main(string[] args)
              {
      
                   using (var fs = new MemoryStream(UTF8Encoding.UTF8.GetBytes(@"<?xml version=""1.0"" encoding=""utf-8""?><test><node id=""123"">
                                  <tag k=""amenity"" v=""fuel"" />
                              </node><node id=""456"">
                                  <tag k=""name"" v=""B"" />
                              </node><node id=""789"">
                                  <tag k=""amenity"" v=""test"" />
                              </node></test>")))
                  {
                      XmlReader reader = XmlReader.Create(fs);
      
                      while (!reader.EOF)
                      {
                          if(reader.Name != "node")
                          {
                              reader.ReadToFollowing("node");
                          }
                          if(!reader.EOF)
                          {
                              XElement node = (XElement)XElement.ReadFrom(reader);
                              int id = (int)node.Attribute("id");
                              Console.WriteLine(id.ToString());
                          }
                      }
                  }
                  Console.ReadLine();
      
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-03
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多