【问题标题】:Select XML attribute value found via another attribute value grouped with it.选择通过与其分组的另一个属性值找到的 XML 属性值。
【发布时间】:2015-04-12 15:40:48
【问题描述】:

我对使用 XML 做任何事情都是全新的,所以我不太了解术语,因此对于可能措辞不当的问题感到抱歉。

我有一个结构如下的 XML 文件:

<userinfo>
    <id username="bobby" password="password123" email="booby@gmail.com" question="Favourite colour" answer="blue"></id>
    <id username="tommy" password="adc123" email="herpderp@gmail.com" question="first pets name" answer="arnold"></id>
</userinfo>

(如有任何改进建议将不胜感激)

我需要根据用户名将问题值作为字符串检索。

我已经有一些与 xml 交互的代码,我返回一个 bool 用于登录,它只是检查信息是否一起存在:

public bool ValidLogin(string username, string password)
{
    XDocument doc = XDocument.Load(@"K:\Sem2\Software Development in Application Frameworks\test stuff\text\loginDetails.xml");

    return doc.Descendants("id")
                .Where(id => id.Attribute("username").Value == username 
                        && id.Attribute("password").Value == password)
                .Any();
}

但那是使用 linq,我不知道如何从 xml 中获取实际值。

如果它像以下那样简单,那就太好了:

 return doc.Descendants("id").Attribute("question").Value.Where(id => id.Attribute("username").Value == enteredUsername);

【问题讨论】:

    标签: c# asp.net xml linq


    【解决方案1】:

    您需要使用Select()First()Last()Single() 来获取值。

    理想情况下,您应该有一个与您的 XML 文件匹配的类:

    public class UserInfo
    {
        public string username {get;set;}
        public string password {get;set;}
        public string question {get;set;}
        public string email {get;set;}
        public string answer {get;set;}
    }
    

    然后把你的方法改成这样:

    public UserInfo GetUserInfo(string username, string password)
    {
        XDocument doc = XDocument.Load(@"K:\Sem2\Software Development in Application Frameworks\test stuff\text\loginDetails.xml");
    
        return doc.Descendants("id")
                    .Where(id => (string)id.Attribute("username") == username 
                            && (string)id.Attribute("password") == password)
                    .Select(s => new UserInfo
                    {
                        username = (string)s.Attribute("username"),
                        password = (string)s.Attribute("password"),
                        email = (string)s.Attribute("email"),
                        question = (string)s.Attribute("question"),
                        answer = (string)s.Attribute("answer")
                    })
                    .FirstOrDefault();
    }
    

    现在在你的调用方法中:

    var userInfo = GetUserInfo(username, password);
    
    // check if user information matches what's in the XML file. return an error if it doesnt.
    if (userInfo == null)
       Console.WriteLine("incorrect username/password");
    
    // you haven't clarified in your question what you're doing with it. But the value of 'question' is accessible like this:
    Console.WriteLine(userInfo.question);
    

    【讨论】:

    • 这在一个表单上效果很好,但我觉得自己像个菜鸟,但是我如何在不同的 aspx 表单上获得“userInfo.question”值,我不想发布url中的值。
    • @Tom 这是一个不同的问题。如果您需要超过 1 个 ASPX 页面上的值,则需要在应用程序中维护某种状态。您可能想稍微了解一下会话状态,或者寻找一些 ASP.NET 用户身份验证示例。
    • @Tom 将您的 html 表单方法设置为 POST。 (GET = URL 查询字符串)。该操作应检查 form = 是否有效。如果成功 -> 重定向到欢迎页面
    【解决方案2】:

    您可以使用SingleSelect 等方法来获取您正在寻找的元素和属性。以我在 LinqPad 中整理的以下示例为例:

    var xml = "<userinfo>"
        + "<id username=\"bobby\" password=\"password123\" email=\"booby@gmail.com\" question=\"Favourite colour\" answer=\"blue\"></id>"
        + "<id username=\"tommy\" password=\"adc123\" email=\"herpderp@gmail.com\" question=\"first pets name\" answer=\"arnold\"></id>"
        + "</userinfo>";
    var xDoc = XDocument.Parse(xml);
    var enteredUsername = "tommy";
    
    //Get idElement by username using Single()
    var idElement = xDoc.Descendants("id")
                    .Single(id => id.Attribute("username").Value == enteredUsername);
    
    //Get question and answer values from idElement
    var question = idElement.Attributes().Single(i => i.Name == "question").Value;
    var answer = idElement.Attributes().Single(i => i.Name == "answer").Value;
    Console.WriteLine(question);
    Console.WriteLine(answer);
    

    或者,您可以使用以下代码将值选择到匿名类中:

    var xml = "...";
    var xDoc = XDocument.Parse(xml);
    var enteredUsername = "tommy";
    var qa = xDoc.Descendants("id")
                    .Where(id => id.Attribute("username").Value == enteredUsername)
                    .Select(id => new { 
                        Question = id.Attribute("question").Value,
                        Answer = id.Attribute("answer").Value})
                    .Single();
    Console.WriteLine(qa.Question);
    Console.WriteLine(qa.Answer);
    

    希望对您有所帮助。

    【讨论】:

    • 使用普通 Single() 的问题是,如果值不匹配,它会引发异常。
    • 感谢您的评论。我只是使用Single() 来说明调用是如何工作的,而无需添加使用FirstOrDefault() 时需要的空检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    相关资源
    最近更新 更多