将XML元素查询为字符串

时间:2013-01-21 20:14:53

标签: c# xml linq

有一个简单的问题:我目前正在尝试学习如何使用XML文件并希望由您运行一个问题:

我遇到了一个问题,我当然可以使用一些帮助。我在下面创建了一个简单的小XML文件(Users.XML):

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <users>
      <user>
        <firstname>Might</firstname>
        <lastname>Guy</lastname>
        <username>SomeUser</username>
      </user>
      <user>
        <firstname>Bob</firstname>
        <lastname>Marley</lastname>
        <username>BobMarley</username>
      </user>       
    </users>

我想要做的是找到一种方法来查询该文件以获取有关用户的特定信息。名字和姓氏无关紧要。现在,在探索之后我发现许多人认为是更好的方法之一:

string firstName;

var data = from item in doc.Descendants("users")
                   where item.Element("user").Element("username").Value == "SomeUser"
                   select new
                   {
                       fname = item.Element("user").Element("firstname").Value
                   };

//Checking to see if anything was found. I know this isn't necessary to pull
//the information. I'm just doing this so I can know to throw an error to the
//screen if none is found
    if (data.Count() > 0)
//Now pull the data. Should only be 1 hit
        foreach (var p in data)
        {
            firstName = p.ToString();
        }
    else
        MessageBox.Show("No such user found");

现在,这个示例代码确实给了我用户的第一个名字。但是,firstName的实际内容是“fname = Might”。我希望它包含的只是“可能”。当然,如果我从选择中删除“fname =”然后它会抛出一个关于不命名字段的错误,所以我碰到了一堵墙。我试着谷歌搜索解决方案,但因为我不确定我在谷歌上搜索它并没有给我带来太多运气。

所以我有3个问题。如果仅仅指向包含信息的教程的方向会更容易,我也会对此感到兴奋!不只是寻找一个简单的解决方案,想要弄清楚为什么会这样,因为我正在尝试学习XML而不仅仅是完成一项任务。

-A)是否可以使用此方法简单地让firstName包含“Might”,而不是“fname = Might”。如果是这样,怎么样?如果没有,是否有另一种方法可以做到这一点?

-B)为什么我需要“fname =”?这与LINQ有关,还是完全是其他的一部分?除了LINQ / XML之外,我还没能在其他任何地方找到这方面的例子,所以我无法得到更详细的原因解释。

-C)这是一个可接受的方法来解决我在示例中要做的事情,也就是根据某个字段(在这种情况下是用户名)查询XML文件中的特定信息?如果没有,你能指出我的方法可能会更好吗?

3 个答案:

答案 0 :(得分:1)

使用:

var data = from item in doc.Descendants("users")
               where item.Element("username").Value == "SomeUser"
               select new
               {
                   fname = item.Element("firstname").Value
               };

var user = data.FirstOrDefault();
var firstName = user.fname;

您正在获取“fname = Might”,因为您正在从查询返回的整个匿名对象上调用ToString。从查询返回的匿名对象实际上具有名为fname的属性。

C)问题:使用此LinqToXml从xml文件读取数据是正确的方法; - )

答案 1 :(得分:1)

这里的问题是您使用的是p.ToString()而不是p.fname。怎么回事:

string firstName, lastName;

var data = from item in doc.Descendants("user")
           where item.Element("username").Value == "SomeUser"
           select new
           {
               fname = item.Element("firstname").Value,
               lname = item.Element("lastname").Value
           };

var p = data.FirstOrDefault();
if(p != null)
{
    firstName = p.fname;
    lastName = p.lname;
}
else
{
    MessageBox.Show("No such user found");
}

要回答问题B,您不需要使用fname =语法。如果您只想要一个值,而不是:

   select new
   {
       fname = item.Element("firstname").Value,
   };

你可以使用:

   select item.Element("firstname").Value;

select new { key = value, key2 = value2 }语法允许您将多个值放入匿名类的对象中,您可以通过名称轻松地从中提取所需的值。

答案 2 :(得分:1)

您的选择语句是投影。

这告诉编译器创建一个具有一个属性的新匿名对象 - 具有属性值的fname。

select new
{
  fname = item.Element("user").Element("firstname").Value
};

这与执行此类操作几乎相同 - 除了编译器为您自动执行此操作。

public class SomeObject
{
  public string fname { get; set; }
  public override ToString()
  {
    return "fname = " + fname;
  }
}

var data = from item in doc.Descendants("users")
                   where item.Element("user").Element("username").Value == "SomeUser"
                   select new SomeObject { fname = item.Element("user").Element("firstname").Value }

然后你的foreach遍历每个元素并在对象上调用toString ..

foreach (var p in data)
{
  firstName = p.ToString();
}

如果你将foreach改为this,它将解决问题:

foreach (var p in data)
{
  firstName = p.fname;
}