简体   繁体   English

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

[英]Linq-to-XML for retrieving all child nodes

I have the following 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>

Using linq in c# I am trying to get all user names (Admin & JimBob in the example above) using the following code 在c#中使用linq我试图使用以下代码获取所有用户名(上例中的Admin和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);

Which isn't working as it only returns "Users" in the result. 哪个不起作用,因为它只返回结果中的“用户”。

I am new to linq can anybody tell me the correct way of doing it please? 我是linq的新手可以有人告诉我正确的做法吗?

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

Thanks all, I have changed my xml as per Aaron Anodide's sugestion which is what it should have been in the first place (my bad). 谢谢大家,我根据Aaron Anodide的消息改变了我的xml,这应该是它本来应该是的(我的坏)。

Xml now looks like: Xml现在看起来像:

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

and use the following code 并使用以下代码

1 Select all user names 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 get password 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;

Both far more elegant than my previous xml code, thanks for your help and pointers. 两者都比我之前的xml代码更优雅,感谢您的帮助和指点。

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

if you are wanting to return a IEnumerable<XName> then use .Name , if you are wanting to reutrn IEnumerable<string> use Name.LocalName . 如果你想要返回一个IEnumerable<XName>然后使用.Name ,如果你想重新计算IEnumerable<string>使用Name.LocalName Its just my opinion but in your class i would set the xdoc as a property. 它只是我的意见,但在你的课堂上我会将xdoc设置为属性。

NEW Update 新的更新


this actually got upvoted today (8/7/2014), which prompted me to look at it and critique my own work. 这实际上在今天(2014年8月7日)得到了投票,这促使我去看它并批评我自己的工作。 I then realized that this is complete crap... 然后我意识到这是完全废话......

  1. As Aaron Anodide commented in the OP question, the Xml architecture was all wrong and that was what was making this such a hard task... 正如Aaron Anodide在OP问题中评论的那样,Xml体系结构都是错误的,而这正是使这个如此艰巨的任务......

  2. Shame on me for enabling crappy code. 我很惭愧,因为它可以实现糟糕的代码。

  3. Shame on me for posting crappy code 发布蹩脚的代码让我感到羞耻

The way it should actually be implemented. 实际应该实施的方式。 VVVVV VVVVV


XML: 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>

Classes: 类别:

#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; }
    }
}

So for the love of god, please don't use anything below the line. 所以对于上帝的爱,请不要在线下使用任何东西。


Update 更新

Sorry it took so long. 对不起,花了这么久。 Here is a little class I put together for you. 这是我为你准备的一个小班。

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];
        }
    }
}
var result = xdoc.Root
                 .Element("Users")
                 .Elements()
                 .Select(x => x.Name);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM