【问题标题】:LINQ to XML - How can I access inner tags in an XML efficiently?LINQ to XML - 如何有效地访问 XML 中的内部标签?
【发布时间】:2016-07-16 09:54:40
【问题描述】:

我有一个如下所示的 XML:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <data>
    <dataname>A</dataname>
    <property>
      <name>One</name>
      <value>1</value>
    </property>
    <property>
      <name>Two</name>
      <value>2</value>
    </property>
  </data>
  <data>
    <dataname>B</dataname>
    <property>
      <name>One</name>
      <value>11</value>
    </property>
    <property>
      <name>Two</name>
      <value>22</value>
    </property>
  </data>
</root>

我正在尝试在 Visual Studio (c#) 中编写一个函数,该函数从 name - value 对中返回 value 部分。到目前为止,我可以通过以下方式实现这一目标 (我知道,目前没有错误检查):

//private static XElement xml = new XElement("root");
//xml = XElement.Load("Defaults.xml"); -> this happens on program initialization
// The program accesses it several times, so I'm keeping it in the memory to avoid excess HDD usage

public int GetDefaultValue(string dataBlock, string propName)
{
    var xx =
        from first in xml.Elements("data")
        where (string)first.Element("dataname") == dataBlock
        select first;

    var yy =
        from second in xx.Elements("property")
        where (string)second.Element("name") == propName
        select second;

    return int.Parse(yy.First().Element("value").Value);
}

我认为这看起来很糟糕,并且在阅读了大量有关 LINQ to XML 的 MSDN 之后,我认为我离使它成为更好的代码更近了一步。每当我尝试使用单个变量执行此操作时,我都没有得到我想要的结果。

有人可以帮我简化一下吗? (所以我可能会知道我做错了什么)

【问题讨论】:

    标签: c# linq linq-to-xml


    【解决方案1】:

    您可以在一个查询中做到这一点:

    public int GetDefaultValue(string dataBlock, string propName)
    {
        var val =
                from data in xml.Elements("data")
                where (string)data.Element("dataname") == dataBlock
                from property in data.Elements("property")
                where (string)property.Element("name") == propName
                select property.Element("value");
    
        return (int)val.First();
    }
    

    【讨论】:

    • 谢谢!奇怪的是,当我尝试类似的东西时,它对我不起作用。
    【解决方案2】:

    试试这个

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Test test = new Test();
                int results = test.GetDefaultValue("A", "One");
            }
        }
        public class Test
        {
            const string FILENAME = @"c:\temp\test.xml";
            XDocument xml = null;
            public Test()
            {
                xml = XDocument.Load(FILENAME);
            }
    
    
            public int GetDefaultValue(string dataBlock, string propName)
            {
    
                return xml.Descendants("data")
                    .Where(x => (string)x.Element("dataname") == dataBlock)
                    .Descendants("property")
                    .Where(y => (string)y.Element("name") == propName)
                    .Select(z => (int)z.Element("value")).FirstOrDefault();
    
            }
        }
    }
    

    【讨论】:

    • 谢谢!这很好用,但我对使用 lambda 表达式还不太熟悉。不过,非常感谢!
    【解决方案3】:

    对于可能有同样问题的VB'ers。

    Public Function GetDefaultValue(dataBlock As String, propName As String) As Integer
        'note - returns zero if not found
        Return (From d In xe.Elements
                Where d.<dataname>.Value = dataBlock
                From p In d.<property>
                Where p.<name>.Value = propName
                Select CInt(p.<value>.Value) Take 1).FirstOrDefault
    End Function
    

    使用这些数据

    Dim xe As XElement = <root>
                             <data>
                                 <dataname>A</dataname>
                                 <property>
                                     <name>One</name>
                                     <value>1</value>
                                 </property>
                                 <property>
                                     <name>Two</name>
                                     <value>2</value>
                                 </property>
                             </data>
                             <data>
                                 <dataname>B</dataname>
                                 <property>
                                     <name>One</name>
                                     <value>11</value>
                                 </property>
                                 <property>
                                     <name>Two</name>
                                     <value>22</value>
                                 </property>
                             </data>
                         </root>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多