使用C#读取XML

时间:2010-07-19 12:45:25

标签: c# xml

我有以下XML文件

<?xml version="1.0" ?> 
<Persons>
<Person>
    <Id>1</Id>
    <Name>temp</Name>
    <Qlid>1234</Qlid>
    <Manager>3</Manager>
</Person>

<Person>
    <Id>2</Id>
    <Name>someone</Name>
    <Qlid>5678</Qlid>
    <Manager>1</Manager>
</Person>

</Persons>

我正在尝试使用以下c#函数

来阅读它
protected void readXmlFile()
    {
        FileStream fs = new FileStream("C:/Documents and Settings/me/Desktop/chart.xml",FileMode.Open);
        XmlTextReader r = new XmlTextReader(fs);

        //debug
        StringWriter st = new StringWriter();

        List<Person> persons = new List<Person>();

        //Loop through persons in XML
        while (r.Read())
        {
            if (r.NodeType == XmlNodeType.Element && r.Name == "Person")
            {
                Person newPerson = new Person();
                while (r.NodeType != XmlNodeType.EndElement)
                {
                    r.Read();
                    if (r.Name == "Id")
                    {
                        st.Write("67");
                        while (r.NodeType != XmlNodeType.EndElement)
                        {
                            r.Read();
                            if (r.NodeType == XmlNodeType.Text)
                            {
                                newPerson.Id = Int32.Parse(r.Value);
                                st.Write(r.Value);
                            }
                        }
                    }

                    r.Read();
                    if (r.Name == "Name")
                    {
                        while (r.NodeType != XmlNodeType.EndElement)
                        {
                            r.Read();
                            if (r.NodeType == XmlNodeType.Text)
                            {
                                newPerson.Name = (r.Value);
                                st.Write("23");
                            }
                        }
                    }

                    r.Read();
                    if (r.Name == "Qlid")
                    {
                        while (r.NodeType != XmlNodeType.EndElement)
                        {
                            r.Read();
                            if (r.NodeType == XmlNodeType.Text)
                            {
                                newPerson.Qlid = (r.Value);
                                st.Write(r.Value);
                            }
                        }
                    }

                    r.Read();
                    if (r.Name == "Manager")
                    {
                        while (r.NodeType != XmlNodeType.EndElement)
                        {
                            r.Read();
                            if (r.NodeType == XmlNodeType.Text)
                            {
                                newPerson.Manager = Int32.Parse(r.Value);
                                st.Write(r.Value);
                            }
                        }
                    }

                    //add to list
                    persons.Add(newPerson);
                    st.Write(90);
                }


            }
        }

        fs.Close();

if(r.Name =“Id”)和类似的ifs由于某种原因永远不会变为真,返回空人类

5 个答案:

答案 0 :(得分:10)

除非你的XML非常庞大,并且无法一次性加载到内存中,否则我几乎肯定不会走这条路。

XmlReader或Linq2Xml上使用XmlDocument的问题是,您缺少XPath或Linq的所有功能,这些功能旨在完全按照您的尝试进行操作这里:从xml中选择特定节点。

或者,看起来您只是将一些xml反序列化为dto,即Person。这正是内置的xml序列化为您所做的。如果你愿意的话,你可以通过dto上的一些属性实现这一点。

但是,关于为什么这个具体不起作用:

检查Person元素,然后在寻找不是结束元素的内容时循环。我的猜测是你希望下一个节点是Name元素。事实并非如此。您的下一个Read()会为您提供一个空白节点。这会抛弃您对所期望元素的所有后续测试。这突出了您正在做的事情的关键问题:这种方法极其脆弱到xml中的细微变化。每次你盲目地执行Read()时,你都假设你知道下一个节点是什么。如果它不是您所期望的,那么您的代码可能会失败,以至于在它实际发生故障之前不易发现。

是否有令人信服的理由使用其他方法?我的直觉是,如果你这样做,你会省去很多麻烦!

答案 1 :(得分:3)

我将重申其他人的建议:使用LINQ to XML。它会更容易

但是,关于您当前代码失败的原因:

r.Read();
if (r.Name == "Id") { ... }
r.Read();
if (r.Name == "Name") { ... }
// etc

这假定它将按照预期的顺序读取节点(不仅仅是元素 - 不要忘记文本节点等)。你应该只是阅读节点,直到你到达当前元素的末尾,并适当地对每个节点作出反应。

但是,这里是一个LINQ to XML的示例,仅用于比较:

XDocument doc = XDocument.Load("foo.xml")
List<Person> persons = doc.Elements("Person")
                          .Select(x => new Person
                             {
                                 Id = (int) x.Element("Id"),
                                 Name = (string) x.Element("Person"),
                                 Manager = (string) x.Element("Manager")
                                 // etc
                             });
                          .ToList();

不可否认,这当前假设 是一个Id元素,但有一些方法可以使它变得更复杂。如您所见,它比使用XmlReader要简单得多。

答案 2 :(得分:1)

您的代码假定XML文件始终采用与以下顺序的数据相同的格式:

  • 编号
  • 名称
  • Qlid
  • 管理器

你不能做出这个假设。

如果您需要使用此方法,则需要重新构建代码以循环,直到达到<\Person>。然后在循环中切换r.Name以设置newPerson的相应属性。

答案 3 :(得分:0)

正如@Rob所说,你的代码正在返回丢失测试的空格。您可以在WhiteSpaceHandling上指定XmlTextReader,这将解决您当前的问题。

r.WhitespaceHandling = WhitespaceHandling.None;

答案 4 :(得分:0)

可能需要使用XmlReader,可能是因为内存限制。在这种情况下,使用XmlReader.ReadSubTree()方法可能是有益的,这样就无需检查EndElement节点类型。此外,由于SubTree的大小较小,因此它们也可以转换为具有较小内存消耗的XmlDocuments。