2015-02-12 2 views
2

Я новичок в том, чтобы что-либо делать с XML, поэтому я не знаю много терминов, поэтому жаль, возможно, плохо сформулированный вопрос.Выберите значение атрибута XML, найденное с помощью другого значения атрибута, сгруппированного вместе с ним.

У меня есть файл XML структурированы так:

<userinfo> 
    <id username="bobby" password="password123" email="[email protected]" question="Favourite colour" answer="blue"></id> 
    <id username="tommy" password="adc123" email="[email protected]" question="first pets name" answer="arnold"></id> 
</userinfo> 

(Любые предложенные улучшения этого будет оценен)

Мне нужно получить значение вопроса в виде строки, основанное на имени пользователя.

У меня есть некоторый код, взаимодействующий с XML уже, где я возвращать логическое значение для входа в систему, которая просто проверяет информацию там вместе:

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); 

ответ

2

Вы должны использовать 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); 
+0

Это отлично работает на одной форме, но я чувствую себя как полный noob, но как мне получить значение «userInfo.question» в другой форме aspx, я не хочу публиковать значение в URL-адресе. – Vereonix

+0

@Tom Это другой вопрос. Если вам нужно значение на более чем одной странице ASPX, вам нужно поддерживать какое-то состояние в своем приложении. Возможно, вам захочется немного узнать о состоянии сеанса или найти некоторые примеры аутентификации пользователей ASP.NET. – rsbarro

+0

@Tom задает метод html формы POST. (GET = URL-запрос). Действие должно проверить, является ли форма = действительной. если успешно -> перенаправить на страницу приветствия – jzm

1

Вы можете использовать такие методы, как Single или Select, чтобы попасть в elem которые вы ищете. Рассмотрим следующий пример, который я положил вместе в LINQPad:

var xml = "<userinfo>" 
    + "<id username=\"bobby\" password=\"password123\" email=\"[email protected]\" question=\"Favourite colour\" answer=\"blue\"></id>" 
    + "<id username=\"tommy\" password=\"adc123\" email=\"[email protected]\" 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); 

Надежда, что помогает.

+0

Проблема с использованием простой Single() заключается в том, что она генерирует исключение, если значения не совпадают. – jzm

+0

Спасибо за комментарий. Я просто использовал 'Single()', чтобы проиллюстрировать, как работают вызовы, не добавляя нулевые проверки, которые вам понадобятся, если вы используете 'FirstOrDefault()'. – rsbarro

Смежные вопросы