【问题标题】:Parsing XML subtrees解析 XML 子树
【发布时间】:2015-10-23 21:16:05
【问题描述】:

我对 C# 还很陌生,我真的很想解决这个问题。

所以基本上我有一个这样的 XML 文件:

<groups>
<group id="1" name="group1" location="null">
    <member id="1" name="Jack" age="32"/>
    <member id="2" name="Tom" age="25"/>
    <member id="3" name="John" age="32"/>
</group>
<group id="2" name="group2" location="null">
        <member id="1" name="Bob" age="31"/>
        <member id="2" name="Michael" age="34"/>
        <member id="3" name="Mike" age="44"/>
</group>

不完全是这样,但它遵循完全相同的格式。所以我想做的是,将一个组的所有成员放入它自己的列表中。所以每个组都有自己的列表。因此,Jack、Tom、John(组 id 1 的成员)将在 list1 中,而 Bob、Michael 和 Mike(组 id 2 的成员)将在 list2 中。我目前有这个,这基本上把所有成员,不管他们的组,放在同一个列表中,这不是我想要的。解决方案可能很简单,我只是没有处理 XML 文件的经验,所以不知道如何使用这个文件。

String XMLURL = "link_to_xml";

using (XmlTextReader reader = new XmlTextReader(XMLURL))
{
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                switch (reader.Name)
                {
                    case "member":
                        if (reader.HasAttributes)
                        {
                            reader.MoveToAttribute(1);
                            players.Add(reader.Value.ToUpper());
                        }
                        break;
                }
                break;
            }
        }
    }
}

【问题讨论】:

  • XML 文件是否太大以至于无法加载到内存中?如果是这样,则需要像您拥有的那样的流式算法。否则,Linq to XML 提供了迄今为止更简单的解决方案。
  • 取决于什么算作“巨大”,它每 20 秒左右有 50 到 400 个条目和更新(添加新条目并删除旧条目)。我觉得这个很大?所以 Linq 解决方案只适用于“静态”XML 文件?
  • 不,不是很大,实际上很小。 Huge 是 10 兆字节或更多,例如What is the best way to parse (big) XML in C# Code?。 Linq to XML 应该没问题。但无论你使用什么,你都需要在文件更改后重新加载。
  • 好的,将尝试 Linq 解决方案。谢谢。

标签: c# xml parsing subtree


【解决方案1】:

您可以使用 XML Linq 轻松完成。

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


namespace ConsoleApplication53
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
             "<groups>" +
                "<group id=\"1\" name=\"group1\" location=\"null\">" +
                    "<member id=\"1\" name=\"Jack\" age=\"32\"/>" +
                    "<member id=\"2\" name=\"Tom\" age=\"25\"/>" +
                    "<member id=\"3\" name=\"John\" age=\"32\"/>" +
                "</group>" +
                "<group id=\"2\" name=\"group2\" location=\"null\">" +
                        "<member id=\"1\" name=\"Bob\" age=\"31\"/>" +
                        "<member id=\"2\" name=\"Michael\" age=\"34\"/>" +
                        "<member id=\"3\" name=\"Mike\" age=\"44\"/>" +
                "</group>" +
             "</groups>";

            XDocument doc = XDocument.Parse(xml);
            var results = doc.Descendants("group").Select(x => new {
                id = (int)x.Attribute("id"),
                name = x.Attribute("name").Value,
                location = x.Attribute("location").Value,
                memebers = x.Elements("member").Select(y => new {
                    id = (int)y.Attribute("id"),
                    name = y.Attribute("name").Value,
                    age = (int)y.Attribute("age")
                }).ToList()
            }).ToList();
        }

    }
}

【讨论】:

    【解决方案2】:

    您可以像这样使用 System.Xml.Linq:

        private List<string[]> GetGroups(string xml)
        {
            List<string[]> result = new List<string[]>();
            XDocument document = XDocument.Parse(xml);
            XElement groups = document.Root;
            foreach (XElement group in groups.Elements("group"))
            {
                result.Add(group.Elements("member").Select(item => item.Attribute("name").ToString()).ToArray());
            }
            return result;
        }
    

    我没有使用测试文件运行它。我只是想让您了解如何使用 System.Xml.Linq 命名空间类。

    【讨论】:

    • XDocument.Parse 出现Data at the root level is invalid. Line 1, position 1. 错误。我正在使用的 XML 文件具有 .php 扩展名(它被称为“xml.php”,但它只是纯 XML),这会导致错误吗? XmlTextReader 阅读它没有问题。 XML 文件不是由我管理的,所以如果这是导致问题的原因,我无法真正更改它,而且它是动态的,所以我也无法真正手动修复它。
    • 你可能只是在文件的开头有一些奇怪的字符。第一个字符是什么?
    • @bulf - 字符串开头可能有一个byte order mark。你是如何将文件加载到内存中的?最好使用XDocument.Load(string filename),因为内部流读取器应该去掉 BOM。
    • 是的。我的示例只是向您展示如何在加载数据后使用这些类。 Load() 可能对你有用。
    • 是的,XDocument.Load 有效,我使用了下面发布的解决方案 jdweng。还是谢谢!
    猜你喜欢
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多