-2

I'll try to keep it short and thank you in advance.

I have created a Quiz. The Questions and answers, as well as the integer for the correct answer are done via get and set , into a constructor and then created in another class by just creating an object and giving it the parameters. it looks as follows:

allQuestions = new Question[3];
allQuestions[0] = new Question("Question1", "answer1", "answer2", 
"answer3", "answer4", 2);

where 2 is the integer that says answer 2 is the correct one.

i do use this array in almost every function in my code. Now i decided to get the questions from a XML Document instead of creating them here. I'm a C# beginner so i played around and could not get it working.

my self made xml looks as follows :

<questions>

<question>

<ID>1</ID>

<questiontext>Peter</questiontext>

<answer1>der</answer1>

<answer2>da</answer2>

<answer3>21</answer3>

<answer4>lol</answer4>

</question>


<question>

<ID>2</ID>

<questiontext>Paul</questiontext>

<antwort1>dasistid2</antwort1>

<antwort2>27</antwort2>

<antwort3>37</antwort3>

<antwort4>47</antwort4>

</question>

</questions>

so 2 basic nodes (?) can you explain me how to read that one and store it into my array so i can still use my e.g. "allQuestions.Question1" ? watched a youtube tutorial, quite a lot, could still not get it working in this project.

using visual studio 2017 , WPF , C#

ASh
  • 34,632
  • 9
  • 60
  • 82
Desory
  • 19
  • 8
  • Why do you sometimes call the tag “answer” and sometimes “antwort”? You shouldn't add a number to your tag names; XML elements are already ordered. If you need to store some kind of ID that should be an attribute. Any you should include an attribute or something in your XML specifying the correct answer. – Dour High Arch Jun 18 '18 at 00:04
  • I do use an integer to check if the input is equal to the integer given by the current question. i would like to add an integer here ,too. So i guess i should extend this to one more node , the int correctanswer? i am using antwort and answer because i did overlook that i still got some in german and wanted to make it as easy as possible so i translated my xml into english, but only halfway i guess, anyway antwort = answer :) – Desory Jun 18 '18 at 00:24

1 Answers1

0

There are a lot of ways to do what you are trying to do. I'll give you a dirty example of a manual solution, as well as a more automatic one that should work. Note that the automatic version won't use your constructor so unless you have an empty constructor defined it may not work for you.

Manual processing using XML Linq:

public IList<Question> ParseXml(string xmlString)
{
    var result = new List<Question>();
    var xml = XElement.Parse(xmlString);
    var questionNodes = xml.Elements("question");
    //If there were no question nodes, return an empty collection
    if (questionNodes == null)
        return result;

    foreach (var questionNode in questionNodes)
    {
        var idNode = questionNode.Element("ID");
        var textNode = questionNode.Element("questiontext");
        var ant1Node = questionNode.Element("antwort1");
        var ant2Node = questionNode.Element("antwort2");
        var ant3Node = questionNode.Element("antwort3");
        var ant4Node = questionNode.Element("antwort4");

        var question = new Question();
        question.Id = Convert.ToInt32(idNode?.Value);

        // note the '?.' syntax. This is a dirty way of avoiding NULL
        // checks. If textNode is null, it returns null, otherwise it
        // returns the textNode.Value property
        question.Text = textNode?.Value;
        question.AnswerOne = ant1Node?.Value;
        question.AnswerTwo = ant2Node?.Value;
        question.AnswerThree = ant3Node?.Value;
        question.AnswerFour = ant4Node?.Value;

        result.Add(question);
    }

    return result;
}

Next we have the XmlSerializer approach. This is not ideal in all situations, but provides an easy way to serialize objects into XML and to deserialize XML into objects.

public QuestionCollection autoparsexml(string xml)
{
    //create the serializer
    XmlSerializer serializer = new XmlSerializer(typeof(QuestionCollection));
    //convert the string into a memory stream
    MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
    //deserialize the stream into a c# object
    QuestionCollection resultingMessage = (QuestionCollection)serializer.Deserialize(memStream);
}

public class QuestionCollection
{
    public List<Question> Questions { get; set; }
}
  • 1
    That is an unbelievable good answer which helps me a lot thank you for that one. I do not quite grasp the XML Serializer but i dont need to on my level I guess. Would you be as kind as to explain further, how does the XML load into the program here? i do only know of the .load method. what in the first 6 lines is as it is by default and what goes hand in hand with my .xml data name ? – Desory Jun 18 '18 at 00:21
  • I wasn't sure where you were storing your XML, so I didn't include that piece in the code. The xml string data can come from anywhere, it all depends on where you're storing it. If you're saving it in a file then you could use something like `File.ReadAllText` to read the file into a string. You would then pass the string you read out of the file into either of the above methods – jluetzenberg Jun 18 '18 at 00:31
  • "to read the file into a string" , hm my xml is stored in the project folder i created it via rightclick and create new -> xml, in the project folder. dont i usually do something like string a = "select first node here" – Desory Jun 18 '18 at 00:37
  • Ah, if the XML file is meant to be part of your project, you could embed it as a resource, then use [this answer](https://stackoverflow.com/a/3314213/3423500) to read the file into text. To embed the file as a resource, right click on your project in Solution Explorer and go to Resources. If it doesn't already have resources it will prompt you to create a resource file, which it will do automatically. Then click on the dropdown for Add Resource and select Existing File, browse to your file and you should be golden – jluetzenberg Jun 18 '18 at 00:45
  • im not sure if that works for me and i dont wanna bother you any longer , but: now i got the array, lets say question[0] with the params (questiontext, answer 1.... int solution) which i can call upon when i need them. well those should go into the xml as you just wrote in the first answer. i wanna be able to select single lines of the xml using something like (pseudo): question[i].questionText = getFromXMLInTheFirstLine /// or so i can actually keep using my constructor , Question q1 = new Question(XMLQuestionNameOne, XMLAnswerName1 ...XMLIntegerSolution) – Desory Jun 18 '18 at 00:53