2016-07-01 6 views
0

Ich erstelle ein Quiz in C# als Konsolen-App.C# XML-Elemente in 2 separaten Listen lesen

Ich habe eine einzige XML-Datei, die a) Fragen b) Antworten und c) falsche Antworten enthält.

Ich kann Fragen aus meiner XML-Datei lesen.

Allerdings kann ich nicht die Logik erarbeiten Ich muss die falschen und richtigen Antworten für jede zufällig generierte Lese Frage zuordnen.

Hier ist eine Kopie meiner XML-Datei.

<?xml version="1.0" encoding="utf-8"?> 
<Question xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <theQuestion>How many players in a football team?</theQuestion> 
    <answerA>12</answerA> 
    <answerB>10</answerB> 
    <answerC>20</answerC> 
    <answerD>11</answerD> 
    <correctAnswer>11</correctAnswer> 
    <theQuestion>How many minutes in a football game?</theQuestion> 
    <answerA>90</answerA> 
    <answerB>45</answerB> 
    <answerC>60</answerC> 
    <answerD>77</answerD> 
    <correctAnswer>90</correctAnswer> 
</Question> 

Hier ist ein Teil meiner Code:

ProcessData data = new ProcessData(); 

    //load questions from XML file and store in list 
    var questions = data.LoadQuizQuestions(); 

    //create a question object 
    Question q = new Question(); 

    //get a question randomly generated from questions list 
    int index = new Random().Next(questions.Count); 

    //display the randomly generated question 
    Console.WriteLine(questions[index]); 

    Console.ReadLine(); 

Hier mein LoadQuizQuestions ist()

public List<string> LoadQuizQuestions() 
    { 
     //create empty list to store quiz questions read in from file 
     List<string> questions = new List<string>(); 

     //load questions from file into list 
     questions = 
     XDocument.Load(@"C:\Development\Learning\Files\qsFile.xml").Descendants("theQuestion").Select(o => o.Value).ToList(); 

     //return list of questions 
     return questions; 
    } 

ich möchte, wenn jede zufällige Frage die dazugehörigen Antworten auf diese Frage wird angezeigt werden auch angezeigt und die "richtige Antwort" in eine Variable eingelesen, gegen die ich die Benutzereingabe überprüfen kann.

Bitte helfen Sie mir zu verstehen, ich weiß, ich bin in der Nähe zu nageln diese :-)

Danke

+0

Besser zeigen Sie Ihre c ode für 'LoadQuizQuestions' – ilans

+0

warum nicht xmlnode verwenden, um herauszufinden, Antwortstatus – Developer

+0

ilans - LoadQuizQuestions liest einfach die Fragen nur aus XML-Datei – xirokx

Antwort

0
  1. die XML-Lesen in eine List<Question> Sammlung
  2. einen Zufallsgenerator Auswahl
    1. Zeigen Sie die Frage und die Optionen
    2. Fragen Sie nach der Benutzereingabe
    3. Vergleichen Sie die Benutzereingabe mit der richtigen Antwort
  3. Profit

EDIT: Ihre XML-Eingabe behandelt Ihre Daten als sequentielle, nicht hierarchisch; Dies wird zu möglichen Problemen führen, wenn Sie versuchen, die Fragen zu lesen.

Sie sollten eine Struktur wie folgt betrachten:

<Questions> 
    <Question> 
     <Title>How many players in a football team?</Title> 
     <Options> 
      <Option>12</Option> 
      <Option>10</Option> 
      <Option>20</Option> 
      <Option IsCorrect='true'>11</Option> 
     </Options> 
    </Question> 
    <Question> 
     <Title>How many minutes in a football game?</Title> 
     <Options> 
      <Option IsCorrect='true'>90</Option> 
      <Option>45</Option> 
      <Option>60</Option> 
      <Option>77</Option> 
     </Options> 
    </Question> 
</Questions> 

Dies wird die XML manuell oder deserialising es direkt in eine List<Question> Sammlung machen leichter zu lesen.

Ich habe die Entscheidung getroffen, in der Option zu bleiben, wenn es eine richtige Antwort ist, wie dies flexibel genug sein kann, um mehrere richtige Antworten.

class Question 
{ 
    public string Title   { get; private set; } 
    public List<Option> Options { get; private set; } 

    public Question() 
    { 
    } 

    public Question(XmlElement question) : this() 
    { 
     this.Title = question["Title"].InnerText; 
     this.Options = question.SelectNodes("Options/Option") 
      .OfType<XmlElement>() 
      .Select(option => new Option(option)) 
      .ToList(); 
    } 
} 

Keine große Sache hier: wir nur eine XmlElement und Delegierten der Option Klasse das Element Deserialisierung lesen.

class Option 
{ 
    public string Title   { get; private set; } 
    public bool IsCorrect  { get; private set; } 

    public Option() 
    { 
    } 

    public Option(XmlElement option) : this() 
    { 
     this.Title = option.InnerText; 
     this.IsCorrect = option.GetAttribute("IsCorrect") == "true"; 
    } 
} 

Gleiches Angebot.

Mit dieser Struktur können Sie etwas tun:

var xml = new XmlDocument(); 
    xml.LoadXml(@"..."); 

var random = new Random(); 
var questions = xml.SelectNodes("//Question") 
    .OfType<XmlElement>() 
    .Select (question => new Question(question)) 
    .OrderBy(question => random.Next()) 
    .ToList(); 

foreach (var question in questions) 
{ 
    Console.ForegroundColor = ConsoleColor.White; 
    Console.WriteLine(question.Title); 
    foreach (var option in question.Options) 
    { 
     Console.ForegroundColor = ConsoleColor.Gray; 
     Console.WriteLine("\t{0}", option.Title); 
    } 
    Console.Write("Choose the right option: "); 
    var answer = Console.ReadLine(); 

    if (question.Options.Any(option => 
     option.IsCorrect && answer.Equals(option.Title, 
      StringComparison.InvariantCultureIgnoreCase))) 
    { 
     Console.ForegroundColor = ConsoleColor.Green; 
     Console.WriteLine("YOU HAVE CHOSEN... WISELY."); 
    } 
    else 
    { 
     Console.ForegroundColor = ConsoleColor.Red; 
     Console.WriteLine("You have chosen poorly!"); 
    } 
} 
+0

Ich kann nur ein Element aus der XML-Datei lesen - "theQuestion" statt aller Elemente, also antworte A-D und die richtige Antwort ... Irgendwelche Ideen, wie ich alle Fragen lesen und in einzelne Frageobjekte einfügen kann? – xirokx

+1

das funktioniert danke – xirokx

0

Wenn Sie eine Frage-Objekt verwenden, die eine Liste von Antworten, wie diese enthält:

public class Question 
{ 
    public int ID { get; set; } 
    public string QuestionText { get; set; } 

    public List<Answer> Answers { get; set; } 

    public string AnswerText { get; set; } 
} 

public class Answer 
{ 
    public string ID { get; set; } 
    public string AnswerText { get; set; } 
} 

Dann können Sie das lesen Fragen und Antworten in diskrete Objekte, etwas wie der Code unten (Disclaimer: nicht getestet, so dass es möglicherweise zur Arbeit optimiert werden muss)

public List<Question> GetQuestions(string xmlFile) 
    { 
     var questions = new List<Question>(); 

     var xDoc = XDocument.Load(xmlFile); 

     var questionNodes = xDoc.Descendants("theQuestion"); 

     foreach (var questionNode in questionNodes) 
     { 

      var question = new Question(); 
      question.QuestionText = questionNode.Value; 

      // do something like this for all the answers 
      var answer = new Answer(); 
      answer.ID = "A"; 
      var answerA = questionNode.Descendants("answerA").FirstOrDefault(); 
      if (answerA != null) 
       answer.AnswerText = answerA.Value; 

      question.Answers = new List<Answer>(); 
      question.Answers.Add(answer); 

      question.AnswerText = 
       questionNode.Descendants("correctAnswer").FirstOrDefault().Value; 
     } 

     return questions; 
    } 
} 

Jetzt, da Sie die Fragen und Antworten in einem einzelnen Objekt haben, können Sie die Frage und die Antworten anzeigen und dann basierend auf Benutzereingaben einen Zeichenfolgenvergleich durchführen, um die Antwort des Benutzers zu überprüfen.

0

Wenn Sie Ihre XML-Struktur ändern würde ich dies tun:

<?xml version="1.0" encoding="utf-8"?> 
<Questions> 
    <Question text="How many players in a football team?"> 
    <answerA>12</answerA> 
    <answerB>10</answerB> 
    <answerC>20</answerC> 
    <answerD>11</answerD> 
    <correctAnswer>11</correctAnswer> 
    </Question> 
    <Question text="How many minutes in a football game?"> 
    <answerA>90</answerA> 
    <answerB>45</answerB> 
    <answerC>60</answerC> 
    <answerD>77</answerD> 
    <correctAnswer>90</correctAnswer> 
    </Question> 
</Questions> 

Dann deserialisieren Verwendung dieser Klassen:

public class Questions 
{ 
    [XmlElement("Question")] 
    public List<Question> QuestionList { get; set; } = new List<Question>(); 
} 

public class Question 
{ 
    [XmlAttribute("text")] 
    public string Text { get; set; } 

    public string answerA { get; set; } 
    public string answerB { get; set; } 
    public string answerC { get; set; } 
    public string answerD { get; set; } 
    public string correctAnswer { get; set; } 
} 

Und diesen Code:

string path = "yourxmlfile.xml"; 

XmlSerializer serializer = new XmlSerializer(typeof(Questions)); 

StreamReader reader = new StreamReader(path); 
var qs = (Questions)serializer.Deserialize(reader); 
reader.Close(); 
+0

[XmlElement ("Frage")] gibt mir einen Fehler "kann nicht auf Konstruktor XmlElement hier aufgrund seiner geschützten Ebene zugreifen", so kann ich Datei mit Ihrer Lösung deserialisieren nicht. – xirokx

+0

Ich habe den obigen Code getestet und es hat funktioniert, also müssen Sie etwas geändert haben. Deinen Code bekannt geben? –

+0

wo kann ich den Code posten? – xirokx