XMLReader 正在跳过元素

Posted

技术标签:

【中文标题】XMLReader 正在跳过元素【英文标题】:XMLReader is skipping elements 【发布时间】:2020-10-07 08:36:50 【问题描述】:

我有以下 XML 文件(带有虚拟数据)

<Query>
    <QuerySQL Source="Dbname" Sql="SQL statement" />
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="SQL statement" />
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="SQL statement" />
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="SQL statement" />
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="SQL statement" />
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="Sql statement">
      <Parameters>
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
      </Parameters>
    </QuerySQL>
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="Sql statement">
      <Parameters>
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
      </Parameters>
    </QuerySQL>
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="Sql statement">
      <Parameters>
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
      </Parameters>
    </QuerySQL>
  </Query>
  <Query>
    <QuerySQL Source="Dbname" Sql="Sql statement">
      <Parameters>
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
        <Parameter Type="Type" />
      </Parameters>
    </QuerySQL>
  </Query>

问题是,第一个 Query 元素在我的 XMLReader 中被完美读取。

然后,当它遇到带参数的那些时,它会跳过所有其他查询。

我不知道为什么。它根本不会出现在阅读器中。

这是我的阅读器方法;

StringReader stringReader = new StringReader(xmlString.ToString());
      using (XmlReader reader = XmlReader.Create(stringReader, GetXmlReaderSettings())) 
        while (reader.Read() && !reader.EOF) 
          if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "Query")) 
            if (reader.ReadToDescendant("QuerySQL")) 
              m_sqlQuery = reader.GetAttribute("Sql");
              m_doublePointCounter = m_sqlQuery.Split(':').Length - 1;
              m_source = reader.GetAttribute("Source");
              if (reader.ReadToDescendant("Parameters")) 
                while (reader.ReadToFollowing("Parameter") && m_parameterCount < m_doublePointCounter) 
                  m_parameterCount++;
                  var types = reader.GetAttribute("Type");
                  m_paramList.Add(types);
                
              
            
          

我希望任何人都可以帮助我解决这个问题。

我需要的是读取每个 Query 元素并读取它的方法。

【问题讨论】:

根据 XML 规范,它是有效的 Xml。它只是没有很好地形成。 【参考方案1】:

ReadToFollowing 方法会遍历所有Parameter 元素。 为避免这种情况,您需要阅读子树。

if (reader.ReadToDescendant("Parameters"))

    using (var innerReader = reader.ReadSubtree())
    
        while (innerReader.ReadToFollowing("Parameter") && m_parameterCount < m_doublePointCounter)
        
            m_parameterCount++;
            var types = innerReader.GetAttribute("Type");
            m_paramList.Add(types);
        
    

【讨论】:

太棒了!这行得通,非常感谢。我是如此接近:D【参考方案2】:

试试 xml linq:

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



namespace ConsoleApplication4

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            string xml = File.ReadAllText(FILENAME);
            XDocument doc = XDocument.Parse(xml);

            var results = doc.Descendants("Query").Select(x => new
            
                source = (string)x.Element("QuerySQL").Attribute("Source"),
                sql = (string)x.Element("QuerySQL").Attribute("Sql"),
                parameters = x.Descendants("Parameter").Select(y => new  type = (string)y.Attribute("Type") ).ToList()
            ).ToList();


        
    



【讨论】:

你有根级别的数组吗?你有命名空间吗?【参考方案3】:

您的 XML 格式不正确 - 您有多个 &lt;Query&gt; 根标签。要使 XML 有效,您需要将重复的 &lt;Query&gt; 标记嵌套在根标记中。

在您解决该问题之前,您无能为力 - 需要 XML 处理器来拒绝您的输入文件。 LINQ 未能处理它,我并不感到惊讶。我很惊讶您没有从您发布的代码中得到解析错误。

【讨论】:

我有,它在“查询”根标签中。所以这不是问题。我刚刚尝试过,当我最后用 /> 关闭每个 SQLQuery 时,它确实检测到所有查询......但是它不解析参数。 检查您的问题 - XML 不包含 &lt;Queries&gt; 根标记。请立即编辑问题,并包含整个 XML 消息(包括根标记上的任何命名空间定义)

以上是关于XMLReader 正在跳过元素的主要内容,如果未能解决你的问题,请参考以下文章

如果没有空格分隔符,为啥 XmlReader 会跳过所有其他元素?

为啥 XmlReader 跳过标签?

C# 使用 XMLReader(?) 读取子元素

XmlReader - 自关闭元素不会触发 EndElement 事件?

从 XmlReader 打印出元素值

使用 xmlReader 在 C# 中过滤特定元素值的大型 XML