【问题标题】:How to read variable child nodes from an xml file?如何从 xml 文件中读取变量子节点?
【发布时间】:2013-12-19 12:01:48
【问题描述】:

我需要解析具有可变数量节点的 xml 配置文件,而这些节点又包含可变数量的子节点。无论我有多少 VM 节点或 vmClient 节点,如何读取所有值?我在这个项目中使用 C# 和 VS2012。 顺便说一句,如果有更好的方法在 xml 文件中构造我的数据,请告诉我!这是xml文件:

<!--VM settings on ESX Server-->
<VM name="DE2008">
    <vmLanguage value = "de"/>
    <vmSnapshot value = "test"/>
    <vmPowerOn value = "true"/>
    <vmClients>
        <vmClient name="ITXPPRO">
            <vmClientSnapshot value="test2"/>
            <vmClientLanguage value="it"/>
        </vmClient>
        <vmClient name="JPXPPRO">
            <vmClientSnapshot value="test3"/>
            <vmClientLanguage value="jp"/>
        </vmClient>
    </vmClients>
</VM>

<VM name="FR2003">
    <vmLanguage value = "fr"/>
    <vmSnapshot value = "test"/>
    <vmPowerOn value = "true"/>
    <vmClients>
        <vmClient name="DAWIN7">
            <vmClientSnapshot value="autotc"/>
            <vmClientLanguage value="da"/>
        </vmClient>
    </vmClients>
</VM>

<!--SQL Servers used as database servers for ePO-->
<sqlServers>
    <sqlName value = "DE2008SQL"/>
    <sqlLanguage value = "de"/>
    <sqlSnapshot value = "sql"/>
</sqlServers>

【问题讨论】:

  • 你试过什么?你看过使用 Linq2Xml 吗?此外,一个文档中不能有多个 xml 根。
  • 如果结构没有改变(经常),我建议你反序列化它,然后只迭代“常规”对象。检查lazyberezovsky的答案。

标签: c# xml xml-parsing


【解决方案1】:

我建议你使用 LINQ to XML

var xdoc = XDocument.Load(path_to_xml);
var query = from vm in xdoc.Descendants("VM")
            select new {
               Name = (string)vm.Attribute("name"),
               Language = (string)vm.Element("vmLanguage").Attribute("value"),
               Snapshot = (string)vm.Element("vmSnapshot").Attribute("value"),
               PowerOn = (bool)vm.Element("vmPowerOn").Attribute("value"),
               Clients = from c in vm.Element("vmClients").Elements()
                         select new {
                            Name = (string)c.Attribute("name"),
                            // etc
                         }
            };

另外我建议你将值直接存储为元素值,或者在属性中,而不是

Language = (string)vm.Element("vmLanguage").Attribute("value")

您将能够使用(如果缺少某些元素,您也不会得到异常)

Language = (string)vm.Element("vmLanguage") // if value stored in element
// or
Language = (string)vm.Attribute("vmLanguage") // if value stored in attribute

前缀vm 对我来说有点奇怪。如果它是vm 数据的一部分,为什么不简单地使用language?所以,我会采用以下配置:

<vm name="DE2008" language="de" shapshot="test" powerOn="true">
    <clients>
        <client name="ITXPPRO" snapshot="test2" language="it"/>
        <client name="ITXPPRO" snapshot="test3" language="jp"/>
    </clients>
</vm>

【讨论】:

  • 感谢您的出色回答。我会按照你的建议去做。我很抱歉,但我是 LINQ 的新手——如何从查询中提取节点属性?我是否必须将其转换为列表或其他内容?非常感谢您的时间和帮助。
  • @baraman 此查询返回匿名类型序列。您可以在 foreach 中枚举它们,或使用var vms = query.ToList() 调用转换为列表。然后您将能够通过索引vms[0].Language 获取项目
  • 非常感谢,很好的回答。
  • @baraman 还要注意一点 - 此处的匿名类型仅用于示例。您可以创建 VMVMClient 类并返回这些类的实例而不是匿名类型
  • 最后一件事,当我执行 foreach 循环查询时,我得到了 VM 的结果,但没有得到客户端的结果 - 它给了我关于 Linq 的长消息。我认为这是因为 Clients 返回另一个列表而不是字符串。如何访问客户列表?
【解决方案2】:

你只是使用这样的东西

    XDocument xDocument = XDocument.Load(yourconfigfilepath);


            var firstresult = xDocument.Descendants("VM");
foreach (var elt in result)
            {
                var childforeachNode = xDocument.Descendants("vmClient");

            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多