Linq-to-XML用于检索所有子节点

时间:2013-08-24 10:21:09

标签: c# xml linq linq-to-xml

我有以下XML

 <?xml version="1.0" encoding="utf-8"?>
 <ErrorServer>
   <ClientIP>
     <AllowAll>false</AllowAll>
     <Client_127_0_0_1>true</Client_127_0_0_1>
   </ClientIP>
   <Users>
     <Admin>
       <Password>passw0r!d</Password>
       <NextError>83</NextError>
       <Active>true</Active>
     </Admin>
     <JimBob>
       <Password>passw0r!d</Password>
       <NextError>83</NextError>
       <Active>true</Active>
     </JimBob>
   </Users>
 </ErrorServer>

在c#中使用linq我试图使用以下代码获取所有用户名(上例中的Admin&amp; JimBob)

    List<string> Result = new List<string>();

    XDocument xdoc = XDocument.Load("ErrorServerConfig.xml");

    //Run query
    var lv1s = from lv1 in xdoc.Descendants("ErrorServer")
               select new
               {
                   Children = lv1.Elements("Users")
               };

    //Loop through results
    foreach (var lv1 in lv1s)
    {
        foreach (var lv2 in lv1.Children)
            Result.Add(lv2.Name.ToString());
    }

    return (Result);

哪个不起作用,因为它只返回结果中的“用户”。

我是linq的新手,任何人都可以告诉我正确的方法吗?

4 个答案:

答案 0 :(得分:4)

var result = xdoc.Descendants("Users")
                 .First()
                 .Elements()
                 .Select(e=>e.Name);

答案 1 :(得分:4)

谢谢大家,我根据Aaron Anodide的消息改变了我的xml,这应该是它本来应该是的(我的坏)。

Xml现在看起来像:

<ErrorServer>
  <Users>
    <User>
      <Username>Admin</Username>
      <Password>passw0r!d</Password>
      <NextError>83</NextError>
      <Active>true</Active>
    </User>
  </Users>
</ErrorServer>

并使用以下代码

1选择所有用户名

        XDocument xdoc = XDocument.Load("ErrorServerConfig.xml");

        //Run query
        var result = from e in xdoc.Descendants("Users").Elements()
             select (string)e.Element("Username");

        //Loop through results
        foreach (string user in result)
        {
            Result += String.Format("{0}\r\n", user);
        }

2获取密码

    XDocument xdoc = XDocument.Load("ErrorServerConfig.xml");

    //Run query
    var result = (from e in xdoc.Descendants("Users").Elements()
                 where (string)e.Element("Username") == userName
                 select e).Descendants("Password").First().Value;

两者都比我之前的xml代码更优雅,感谢您的帮助和指示。

答案 2 :(得分:2)

var res =  XDocument.Load("yourpath")
    .Descendants("Users").Elements()
    .Select(xe => xe.Name.LocalName);

如果您想要返回IEnumerable<XName>,请使用.Name,如果您想要重新IEnumerable<string>使用Name.LocalName。它只是我的意见,但在你的课堂上我会将xdoc设置为属性。

新更新


这实际上今天(2014年8月7日)被提升了,这促使我去看它并批评我自己的工作。然后我意识到这是完全废话......

  1. 正如Aaron Anodide在OP问题中评论的那样,Xml架构都是错误的,而这正是使这项任务变得艰巨的任务......

  2. 因为启用糟糕的代码而感到羞耻。

  3. 因发布蹩脚的代码而感到羞耻

  4. 实际应该实施的方式。 VVVVV


    XML:

    <?xml version="1.0" encoding="utf-8" ?>
    <ErrorServer>
      <ClientIP>
        <AllowAll>false</AllowAll>
        <Address>127.0.0.1</Address>
      </ClientIP>
      <Users>
        <User>
          <Username>Admin</Username>
          <Password>passw0r!d</Password>
          <NextError>83</NextError>
          <Active>true</Active>
        </User>
        <User>
          <Username>JimBob</Username>
          <Password>passw0r!d</Password>
          <NextError>83</NextError>
          <Active>true</Active>
        </User>
      </Users>
    </ErrorServer>
    

    类:

    #region Referencing
    
    using System;
    using System.IO;
    using System.Linq;
    using System.Xml.Serialization;
    
    #endregion
    
    namespace Stack
    {
        public class Program
        {
            public Program()
            {
                ErrorServer = ErrorServer.Deserialize( "path" );
            }
    
            public ErrorServer ErrorServer { get; set; }
    
            // This way you dont actually have to deal with LINQ and XML.
            // It's just as easy to create a few classes to hold your data, so you can use xml serialization.
            public User GetUserInfoByName( string name )
            {
                return
                    ErrorServer.Users.FirstOrDefault(
                        user => user.Username.Equals( name, StringComparison.CurrentCultureIgnoreCase ) );
            }
        }
    
        [Serializable]
        public class ErrorServer
        {
            public ClientIP ClientIP { get; set; }
    
            [XmlArrayItem( "User" )]
            public User[] Users { get; set; }
    
            public static ErrorServer Deserialize( string path )
            {
                using (var stream = new FileStream( path, FileMode.Open ))
                    return new XmlSerializer( typeof (ErrorServer) ).Deserialize( stream ) as ErrorServer;
            }
        }
    
        [Serializable]
        public class ClientIP
        {
            public bool AllowAll { get; set; }
    
            public string Address { get; set; }
        }
    
        [Serializable]
        public class User
        {
            public string Username { get; set; }
    
            public string Password { get; set; }
    
            public double NextError { get; set; }
    
            public bool Active { get; set; }
        }
    }
    

    所以对于上帝的爱,请不要在线下使用任何东西。


    更新

    抱歉这花了这么久。这是我为你准备的一个小班。

    using System;
    using System.Linq;
    using System.Xml.Linq;
    
    namespace StackTesting
    {
        class Program
        {
            public class User
            {
             public string Username { get; set; }
             public string Pass { get; set; }
             public double Error { get; set; }
             public bool Active { get; set; }
    
              public User() { }
            }
    
            Public XDocument xDoc { get; set; }
    
            static void Main(string[] args)
            {
             xDoc = XDocument.Load(@"C:\Users\Trae\Documents\visual studio 2012\Projects\StackTesting\StackTesting\XMLFile1.xml");
              var user = (User) GetUserInfo("Admin");
            }
    
            public static User GetUserInfo(string UserName)
            {
              return xDoc.Root.Elements("Users").Elements()
                .Where(xe => xe.Element(XName.Get("Username")).Value == UserName)
                .Select(xe =>
                  new User
                  {
                    Username = xe.Element(XName.Get("Username")).Value,
                    Pass = xe.Element(XName.Get("Password")).Value,
                    Error = double.Parse(xe.Element(XName.Get("NextError")).Value),
                    Active = bool.Parse(xe.Element(XName.Get("Active")).Value)
                  }).ToArray()[0];
            }
        }
    }
    

答案 3 :(得分:1)

var result = xdoc.Root
                 .Element("Users")
                 .Elements()
                 .Select(x => x.Name);