[英]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 并使用以下代码
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);
}
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设置为属性。
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...
然后我意识到这是完全废话......
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体系结构都是错误的,而这正是使这个如此艰巨的任务......
Shame on me for enabling crappy code. 我很惭愧,因为它可以实现糟糕的代码。
Shame on me for posting crappy code 发布蹩脚的代码让我感到羞耻
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; }
}
}
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.