将XML元素读取到两个单独的列表中

本文关键字:两个 单独 列表 元素 XML 读取 | 更新日期: 2023-09-27 17:54:19

我正在创建一个c#测试作为控制台应用程序。

我有一个XML文件,其中包含a)问题b)答案和c)错误答案。

我可以从XML文件中读取问题。

然而,我无法找出逻辑,我需要将每个随机生成的阅读问题的错误和正确答案联系起来。

这是我的XML文件副本。

<?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>

下面是我的部分代码:

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

这是我的LoadQuizQuestions()

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

我希望在显示每个随机问题时,也显示该问题的相关答案,并将"正确答案"读取到一个变量中,我可以根据该变量检查用户输入。

请帮助我理解,我知道我接近钉子这个:-)

谢谢

将XML元素读取到两个单独的列表中

  1. 读取xml到List<Question>集合
  2. 随机选择一件物品
    1. 显示问题和选项
    2. 请求用户输入
    3. 将用户输入与正确答案进行比较
  3. 利润

EDIT:您的XML输入将您的数据视为顺序,而不是分层的;当你试图阅读问题时,这会导致潜在的问题。

你应该考虑这样的结构:

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

这将使手动读取XML或将其直接反序列化为List<Question>集合更容易。

我决定保留正确答案的选项,因为这可以灵活地处理多个正确答案。

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

这里没什么大不了的:我们只是读取一个XmlElement并将项目反序列化委托给Option类。

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";
    }
}

相同的协议。

使用这个结构,你可以这样做:

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!");
    }
}

如果使用包含答案列表的question对象,如下所示:

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

然后你可以把问题和答案读成离散的对象,就像下面的代码(免责声明:没有测试这个,所以它可能需要调整工作)

   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("answerswerA").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;
    } 
}

现在您已经将问题和答案放在一个对象中,您可以显示问题和答案,然后根据用户输入执行字符串比较以检查用户的答案。

您可以根据需要检查我的逻辑以获取XMLNode的值。

如何使用c#获取XML文件中的节点值

如果你可以改变你的xml结构,我会这样做:

<?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>

然后使用这些类反序列化:

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

和这个代码:

string path = "yourxmlfile.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Questions));
StreamReader reader = new StreamReader(path);
var qs = (Questions)serializer.Deserialize(reader);
reader.Close();