【问题标题】:How to properly search xml document using LINQ C#如何使用 LINQ C# 正确搜索 xml 文档
【发布时间】:2015-09-29 20:42:06
【问题描述】:

我很难弄清楚如何正确搜索 xml 文档。我今天一直在疯狂地阅读其他表格,但似乎无法理解。希望有人能给我一些更详细的信息,说明如何以正确的方式做到这一点以及为什么使用 LINQ。这是 XML 文件。

<?xml version="1.0" encoding="utf-8"?>
<body>
  <Customers>
    <Client>
      <Firstname Value="someguy" />
      <LastName Value="test" />
      <PhoneNumber Value="541555555" />
      <Address Value="55 nowhere" />
      <City Value="sometown" />
      <State Value="somestate" />
    </Client>
  </Customers>
</body>

我想要完成的是返回与客户姓名匹配的每个元素的所有值。这是我的代码。

       IEnumerable<XElement> test = doc.Root.Descendants()
            .Where(nodeName => nodeName.Name == "Client"
            && nodeName.Descendants().Any(x => x.Name == "Firstname"
            && x.Value == "someguy"));

        foreach (XElement m in test)
        {
            MessageBox.Show(m.ToString());
        }

非常感谢您的帮助。如果可能的话,还请解释一下使用 LINQ 的想法是什么,如果你愿意的话。不太确定如何解释我的要求,但大多数情况下只是更多地了解它的工作方式或格式等......

编辑

我已经尝试了给出的解决方案,但似乎仍然没有任何效果。请告诉我我在这里做错了什么。

        private void button2_Click(object sender, EventArgs e)
    {
        string seach = txtSearch.Text;

        XDocument doc = XDocument.Load(@"C:\users\tim\desktop\test.xml");

        var result = doc.Elements("Customers")
            .Elements("Client")
            .Where(x => x.Elements("Firstname")
                         .Where(c => c.Attribute("Value").Value == "someguy")
                         .Any())
            .ToList();

        foreach (var m in result)
        {
            MessageBox.Show(m.ToString());
        }
    }

编辑:

好的,我现在已经让它工作并输出了我正在寻找的数据。有人可以告诉我是否有更有效的方法来执行我在此编辑下方发布的内容。

        private void button2_Click(object sender, EventArgs e)
    {
        string seach = txtSearch.Text;

        XDocument doc = XDocument.Load(@"C:\users\tim\desktop\test.xml");

        var result = (from clientNode in doc.Root.Descendants("Client")
                      from name in clientNode.Descendants("Firstname")
                      where name.Attribute("Value").Value == "someguy"
                      select new
                      {
                          Fname = clientNode.Element("Firstname").Attribute("Value").Value,
                          Lname = clientNode.Element("LastName").Attribute("Value").Value,
                          Phone = clientNode.Element("PhoneNumber").Attribute("Value").Value,
                          Address = clientNode.Element("Address").Attribute("Value").Value,
                          City = clientNode.Element("City").Attribute("Value").Value,
                          State = clientNode.Element("State").Attribute("Value").Value
                      });

        foreach (var m in result)
        {
            MessageBox.Show(m.Fname + "\n" +
                            m.Lname + "\n" +
                            m.Phone + "\n" +
                            m.Address + "\n" +
                            m.City + "\n" +
                            m.State);
        }

【问题讨论】:

  • 很难理解你想要什么。如果满足Firstname.Value="someguy" 条件,你想得到Client 节点吗?
  • 基本上我要做的是获取与我的条件匹配的元素内每个元素的所有值。我正在寻找“someguy”我需要他的所有信息#他的地址等...
  • @Timg XElement doc = XElement.Parse(xml);
  • 所以我必须将 xml 放入代码本身? vs 从单个文件访问它?
  • @Timg 你读过我回答的注释部分吗?

标签: c# xml linq


【解决方案1】:

您可以使用XElement 并使用如下 LINQ 查询进行搜索:

XElement doc = XElement.Parse(xml);
var result = doc.Elements("Customers")
                .Elements("Client")
                .Where(x => x.Elements("Firstname")
                             .Where(c => c.Attribute("Value").Value == "someguy")
                             .Any())
                .ToList();

所以输入:

var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<body>
    <Customers>
    <Client>
        <Firstname Value=""someguy"" />
        <LastName Value=""some last name"" />
        <PhoneNumber Value=""123456"" />
        <Address Value=""some where"" />
        <City Value=""some town"" />
        <State Value=""some state"" />
    </Client>
    <Client>
        <Firstname Value=""someotherguy"" />
        <LastName Value=""some other last name"" />
        <PhoneNumber Value=""123456"" />
        <Address Value=""some other where"" />
        <City Value=""some other town"" />
        <State Value=""some other state"" />
    </Client>
    </Customers>
</body>";

XElement doc = XElement.Parse(xml);
var result = doc.Elements("Customers")
                .Elements("Client")
                .Where(x => x.Elements("Firstname")
                             .Where(c => c.Attribute("Value").Value == "someguy")
                             .Any())
                .ToList();

结果将是:

<Client>
    <Firstname Value=""someguy"" />
    <LastName Value=""some last name"" />
    <PhoneNumber Value=""123456"" />
    <Address Value=""some where"" />
    <City Value=""some town"" />
    <State Value=""some state"" />
</Client>

您可以显示值,例如:

MessageBox.Show(string.Format("Firstname: {0}\nLastName: {1}\nPhoneNumber: {2}\nAddress: {3}\nCity: {4}\nState: {5}",
                result[0].Element("Firstname").Attribute("Value").Value,
                result[0].Element("LastName").Attribute("Value").Value,
                result[0].Element("PhoneNumber").Attribute("Value").Value,
                result[0].Element("Address").Attribute("Value").Value,
                result[0].Element("City").Attribute("Value").Value,
                result[0].Element("State").Attribute("Value").Value));

注意:

  • 如果您知道结果应该包含 0 或 1 个元素,则可以使用 FirstOrDefault() 代替 ToList()
  • 元素名称区分大小写,例如,请注意 Firstname
  • 您可以使用XElement.Load() 从文件加载,例如XElement doc = XElement.Load(@"d:\file.xml");
  • 如果您以这种方式选择元素,查询将更加容错.Where(c =&gt; c.Name.ToString().ToLower() == "Customers".ToLower())
  • 这样选择属性查询会更容错.Where(c =&gt; c.Attributes("Value").Where(a=&gt;a.Value == "someguy").Any())

【讨论】:

  • 很好的解决方案,但应该注意的是,它不会检查元素是否实际存在,并且会抛出异常,例如,Customers 元素不存在。此外,您可以使用.Element("Customers"),而不是.Elements("Customers").First()
【解决方案2】:

作为@Reza Aghaei 的解决方案的替代方案,XPath 也是一种解决方案

var xml =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<body>
    <Customers>
    <Client>
        <Firstname Value=""someguy"" />
        <LastName Value=""some last name"" />
        <PhoneNumber Value=""123456"" />
        <Address Value=""some where"" />
        <City Value=""some town"" />
        <State Value=""some state"" />
    </Client>
    <Client>
        <Firstname Value=""someotherguy"" />
        <LastName Value=""some other last name"" />
        <PhoneNumber Value=""123456"" />
        <Address Value=""some other where"" />
        <City Value=""some other town"" />
        <State Value=""some other state"" />
    </Client>
    <Client>
        <Firstname Value=""someguy"" />
        <LastName Value=""some other last name"" />
        <PhoneNumber Value=""12345634543"" />
        <Address Value=""some other where"" />
        <City Value=""some other town"" />
        <State Value=""some other state"" />
    </Client>
    </Customers>
</body>";
XElement doc = XElement.Parse(xml);

foreach(var client in doc
 .XPathSelectElements("./Customers/Client/Firstname[@Value='someguy']")
 .Select(x => x.Parent))
    Console.WriteLine (client);

如果您更喜欢 Linq To Xml 解决方案:

var results = (from c in doc.Descendants("Client")
            from f in c.Descendants("Firstname")
             where (string)f.Attribute("Value") == "someguy"
             select c).ToList();
foreach(var r in results)
    Console.WriteLine (r);

How to: Write Linq to Xml Queries with Complex Filtering

【讨论】:

  • 我将编辑我的主要帖子,但由于某种原因,我尝试使用您给我的解决方案,但仍然没有骰子。我不知道我在这里做错了什么,请帮我解释一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多