C# xml в цикле for

213
20 апреля 2017, 13:53

Помогите разобраться с циклом и xml. Это мой первый вопрос, я школьник, пытаюсь написать программу по созданию теста для одноклассников. Я создал форму, в ней динамически создал боксы и чекбоксы. Скриншот. Можно добавлять сколько угодно табов...

Мне нужно получить следующий результат:

<test>
  <head>NAME OF THE TEST 2017</head>
  <description>Тест по Математики за 2016 год</description>
  <qw>
    <q text="how match 2+2" src="">
      <a right="no">1</a>
      <a right="no">1,5</a>
      <a right="no">45</a>
      <a right="yes">4</a>
    </q>
    <q text="Наше главное преимущество в том, что каждое тестирование уникально....х." src="">
      <a right="no">Вика</a>
      <a right="no">Настя</a>
      <a right="yes">Катя</a>
    </q>
    .....
    .... остальные вопросы N число....
    .....
  </qw>
  <levels>
    <level score="1" text="Тест пройден" />
  </levels>
</test>

Использую for для сбора данных из боксов, обращаясь к TabControl:

XDocument xdoc = new XDocument();
XElement testXML = new XElement("test");//заголовок
XElement headXML = new XElement("head","заголовок XML");//заголовок
XElement discriptionXML = new XElement("Discriptions","ОПИСАНИЕ ТЕСТА");//описание теста
XElement qwXML = new XElement("qw");//начала вопросов
XElement questionXMLX = new XElement("q");// начало вопроса
XElement questionXMLAY = new XElement("a");// ответ
XElement questionXMLAN = new XElement("a");// ответ
XAttribute DiscriptionAttr = new XAttribute("text", "ПУСТО");//собираем текст
XAttribute questionXAttr = new XAttribute("text", "ПУСТО");//собираем текст
XAttribute questionSRCXAttr = new XAttribute("src", "ПУСТО");//собираем картинку
XAttribute questionAAttrN = new XAttribute("right", "no");//собираем текст
XAttribute questionAAttrY = new XAttribute("right", "yes");//собираем текст

// TextBoxQuest.Tag = "TxBOXquery"; //Поле вопроса
//RadioButton[i].Tag = "rbAnswer"; //Радиобуттон правильного ответа
//TextBoxAns[i].Tag = "TxBOXAnswer";//Варианты ответа
questionXMLAY.Add(questionAAttrY);
questionXMLAN.Add(questionAAttrN);
string ctrl ="";//собираем текст из полей
string tagz = ""; //смотрим что это за поле
int qcount = tabControl1.TabCount * (CountAnswerInTest*2);
for (int itab = 0; itab < tabControl1.TabCount; itab++)//перебираем табы
{
    for (int i = 0; i <= CountAnswerInTest*2; i++)//перебираем внутренние ответы
    {
        ctrl = tabControl1.Controls[itab].Controls[i].Text;//собираем текст из полей
        tagz = tabControl1.Controls[itab].Controls[i].Tag.ToString(); //смотрим что это за поле
        Console.WriteLine(tagz);//debug
        if (tagz == "TxBOXquery") //если равно TxBOXquery то это поле с вопросом
        {
            Console.WriteLine(ctrl);//debug
            Console.WriteLine(questionXMLX);//debug 
            questionXMLX.Add(ctrl);//Добавляем его 
            Console.WriteLine(questionXMLX);//debug
        }//пишем вопрос
        if (tagz == "rbAnswer")//если равно rbAnswer то это поле с ответом
            if (ctrl == "")//если текста нет, то скорее всего это радиобуттон\
            {
                Control ctrlb = tabControl1.Controls[itab].Controls[i]; //присваем чекбокс
                if (Convert.ToString(ctrlb) == "System.Windows.Forms.RadioButton, Checked: False") //смотрим нажат или нет
                {
                    Console.WriteLine("False");//debug
                                               // questionXMLA.Add(questionAAttrN);
                    int ix = ++i;//убираем непонятные пустые поля
                    string ctrlX = tabControl1.Controls[itab].Controls[ix].Text;//собираем текст из полей
                    questionXMLX.Add(questionXMLAN, ctrl, ctrlX); //добавляем в xml
                }
                else //если чекбокс не нажат то пишем NO
                {
                    int ix = ++i;//убираем непонятные пустые поля
                    string ctrlX = tabControl1.Controls[itab].Controls[ix].Text;//собираем текст из полей
                    Console.WriteLine("True");//debug
                    questionXMLX.Add(questionXMLAN, ctrl, ctrlX);/ добавляем в xml
                    // questionXMLA.Add(questionAAttrY);
                }
            }
    }
    qwXML.Add(questionXMLX);// добавляем всё в блок <qw>
}//закончили перебирать табы
testXML.Add(headXML);
testXML.Add(discriptionXML);
testXML.Add(qwXML);
xdoc.Add(testXML);
xdoc.Save("myXML2.xml");

И получаю следущий результат:

<?xml version="1.0" encoding="utf-8"?>
<test>
  <head>заголовок XML</head>
  <Discriptions>ОПИСАНИЕ ТЕСТА</Discriptions>
  <qw>
    <q>Пишем вопрос тут 11
<a right="no" />Ответ 10
<a right="no" />Ответ 11
<a right="no" />Ответ 12Пишем вопрос тут 22
<a right="no" />Ответ 20
<a right="no" />Ответ 21
<a right="no" />Ответ 22Пишем вопрос тут 33
<a right="no" />Ответ 30
<a right="no" />Ответ 31
<a right="no" />Ответ 32</q>
    <q>Пишем вопрос тут 11
<a right="no" />Ответ 10
<a right="no" />Ответ 11
<a right="no" />Ответ 12Пишем вопрос тут 22
<a right="no" />Ответ 20
<a right="no" />Ответ 21
<a right="no" />Ответ 22</q>
    <q>Пишем вопрос тут 11
<a right="no" />Ответ 10
<a right="no" />Ответ 11
<a right="no" />Ответ 12Пишем вопрос тут 22
<a right="no" />Ответ 20
<a right="no" />Ответ 21
<a right="no" />Ответ 22Пишем вопрос тут 33
<a right="no" />Ответ 30
<a right="no" />Ответ 31
<a right="no" />Ответ 32</q>
 </qw>
</test>

Ошибка получается вот тут, не добавляется новый вопрос, хотя циклы проходят нормально и срабатывает questionXMLX.Add(ctrl), который должен добавлять новый <q>:

<a right="no" />Ответ 12Пишем вопрос тут 22

А надо, чтоб было вот так:

<a right="no" />Ответ 12</q>
<q>Пишем вопрос тут 22

Не понимаю, почему неправильно работает:

Console.WriteLine(ctrl);//debug
Console.WriteLine(questionXMLX);//debug 
questionXMLX.Add(ctrl);//Добавляем его в xml 
Console.WriteLine(questionXMLX);//debug

Помогите, пожалуйста.

Answer 1

Так происходит, потому что используется один и тот же XElement. Один new XElement("q") эквивалентен <\q>. Для решения твоей задачи надо каждый раз создавать новый XElement, а в конце итерации цикла добавлять в коллекцию qwXML.Add(questionXMLX).

Что-то вроде такого:

   XElement questionXMLX = new XElement("q");
   // Логика по заполнению questionXMLX
   qwXML.Add(questionXMLX);

Чтобы лучше понять логику взаимодействия с XElement вот пример кода и XML, который получается в итоге:

XElement contacts =
new XElement("Contacts",
    new XElement("Contact",
        new XElement("Name", "Patrick Hines"),
        new XElement("Phone", "206-555-0144", 
            new XAttribute("Type", "Home")),
        new XElement("phone", "425-555-0145",
            new XAttribute("Type", "Work")),
        new XElement("Address",
            new XElement("Street1", "123 Main St"),
            new XElement("City", "Mercer Island"),
            new XElement("State", "WA"),
            new XElement("Postal", "68042")
        )
    )
);

На выходе:

<?xml version="1.0" encoding="utf-8"?>
<Contacts>
  <Contact>
    <Name>Patrick Hines</Name>
    <Phone Type="Home">206-555-0144</Phone>
    <phone Type="Work">425-555-0145</phone>
    <Address>
      <Street1>123 Main St</Street1>
      <City>Mercer Island</City>
      <State>WA</State>
      <Postal>68042</Postal>
    </Address>
  </Contact>
</Contacts>
READ ALSO
Форматирование кода в VS Code (C#)

Форматирование кода в VS Code (C#)

Как настроить форматирование кода в VS Code под C# привык к нормальному компактному синтаксису в стиле Java, те

458
Как считывать по нескольку байтов из файла?

Как считывать по нескольку байтов из файла?

У меня есть файл для чтения(может быть любой)Мне нужно считывать из него определенное количество байт(к примеру 2)

209
Как очистить консоль C#?

Как очистить консоль C#?

Каким образом возможно очистить консоль в C#?

620
Kohana Auth Custom Role

Kohana Auth Custom Role

Модуль Auth работает с привязкой к ролям login и adminКак реализовать авторизацию на основании других ролей

241