在 C# 中使用 XmlReader 读取 Xml [英] Reading Xml with XmlReader in C#

查看:35
本文介绍了在 C# 中使用 XmlReader 读取 Xml的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试尽可能快地阅读以下 Xml 文档,并让其他类管理每个子块的阅读.

<账户><账户><NameOfKin></NameOfKin><声明可用><声明></声明></StatementsAvailable></帐户></帐户></应用程序池>

但是,我正在尝试使用 XmlReader 对象来读取每个帐户以及随后的StatementsAvailable".您是否建议使用 XmlReader.Read 并检查每个元素并处理它?<​​/p>

我想过分开我的类来正确处理每个节点.所以有一个 AccountBase 类,它接受一个 XmlReader 实例,该实例读取 NameOfKin 和有关该帐户的其他几个属性.然后我想通过 Statements 进行交互,让另一个类自己填写关于 Statement 的内容(然后将其添加到 IList 中).

到目前为止,我已经通过执行 XmlReader.ReadElementString() 完成了每类"部分,但我无法锻炼如何告诉指针移动到 StatementsAvailable 元素并让我遍历它们并让另一个类读取每个这些属性.

听起来很简单!

解决方案

我对 XmlReader 的体验是很容易不小心读到太多.我知道您已经说过要尽快阅读它,但是您是否尝试改用 DOM 模型?我发现 LINQ to XML 使 XML 的工作变得很多更容易.

如果您的文档特别大,您可以通过从 XmlReader 为每个文档创建一个 XElement 来组合 XmlReader 和 LINQ to XML以流式方式处理外部"元素:这使您可以在 LINQ 到 XML 中完成大部分转换工作,但在任何时候仍然只需要内存中的一小部分文档.这是一些示例代码(稍微改编自 这篇博文):

静态 IEnumerableSimpleStreamAxis(string inputUrl,字符串元素名称){使用 (XmlReader reader = XmlReader.Create(inputUrl)){reader.MoveToContent();而 (reader.Read()){if (reader.NodeType == XmlNodeType.Element){if (reader.Name == elementName){XElement el = XNode.ReadFrom(reader) as XElement;如果 (el != null){收益回报 el;}}}}}}

我以前曾用它将 StackOverflow 用户数据(非常庞大)转换成另一种格式 - 效果很好.

来自radarbob 的编辑,由Jon 重新格式化 - 虽然不太清楚是指哪个读得太远"问题......

这应该会简化嵌套并解决读得太远"的问题.

using (XmlReader reader = XmlReader.Create(inputUrl)){reader.ReadStartElement("theRootElement");while (reader.Name == "TheNodeIWant"){XElement el = (XElement) XNode.ReadFrom(reader);}reader.ReadEndElement();}

这解决了读得太远"的问题,因为它实现了经典的 while 循环模式:

初始读取;(虽然我们还没有到最后"){做东西;读;}

I'm trying to read the following Xml document as fast as I can and let additional classes manage the reading of each sub block.

<ApplicationPool>
    <Accounts>
        <Account>
            <NameOfKin></NameOfKin>
            <StatementsAvailable>
                <Statement></Statement>
            </StatementsAvailable>
        </Account>
    </Accounts>
</ApplicationPool>

However, I'm trying to use the XmlReader object to read each Account and subsequently the "StatementsAvailable". Do you suggest using XmlReader.Read and check each element and handle it?

I've thought of seperating my classes to handle each node properly. So theres an AccountBase class that accepts a XmlReader instance that reads the NameOfKin and several other properties about the account. Then I was wanting to interate through the Statements and let another class fill itself out about the Statement (and subsequently add it to an IList).

Thus far I have the "per class" part done by doing XmlReader.ReadElementString() but I can't workout how to tell the pointer to move to the StatementsAvailable element and let me iterate through them and let another class read each of those proeprties.

Sounds easy!

解决方案

My experience of XmlReader is that it's very easy to accidentally read too much. I know you've said you want to read it as quickly as possible, but have you tried using a DOM model instead? I've found that LINQ to XML makes XML work much much easier.

If your document is particularly huge, you can combine XmlReader and LINQ to XML by creating an XElement from an XmlReader for each of your "outer" elements in a streaming manner: this lets you do most of the conversion work in LINQ to XML, but still only need a small portion of the document in memory at any one time. Here's some sample code (adapted slightly from this blog post):

static IEnumerable<XElement> SimpleStreamAxis(string inputUrl,
                                              string elementName)
{
  using (XmlReader reader = XmlReader.Create(inputUrl))
  {
    reader.MoveToContent();
    while (reader.Read())
    {
      if (reader.NodeType == XmlNodeType.Element)
      {
        if (reader.Name == elementName)
        {
          XElement el = XNode.ReadFrom(reader) as XElement;
          if (el != null)
          {
            yield return el;
          }
        }
      }
    }
  }
}

I've used this to convert the StackOverflow user data (which is enormous) into another format before - it works very well.

EDIT from radarbob, reformatted by Jon - although it's not quite clear which "read too far" problem is being referred to...

This should simplify the nesting and take care of the "a read too far" problem.

using (XmlReader reader = XmlReader.Create(inputUrl))
{
    reader.ReadStartElement("theRootElement");

    while (reader.Name == "TheNodeIWant")
    {
        XElement el = (XElement) XNode.ReadFrom(reader);
    }

    reader.ReadEndElement();
}

This takes care of "a read too far" problem because it implements the classic while loop pattern:

initial read;
(while "we're not at the end") {
    do stuff;
    read;
}

这篇关于在 C# 中使用 XmlReader 读取 Xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆