Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Вопрос про XML


Автор: DCamer 7.7.2011, 21:19
Здравствуйте. Есть программа, работающая с XML-документами, нужно сделать так, чтобы программа читал определённый, выбранный в самый программе узел. Например, в XML-документе есть такие данные:
Код

<Question id="1" text="Question 1">
   <Answer text="Answer 1" />
   <Answer text="Answer 2" />
</Question>
<Question id="2" text="Question 2">
   <Answer text="Answer 1" />
   <Answer text="Answer 2" />
</Question>

А в программе есть окно выбора ID вопроса, и нужно чтобы, если пользователем выберет, скажем ID 2, загрузился второй вопрос. Подскажите пожалуйста, как такое сделать?  smile 

Автор: xvr 8.7.2011, 16:57
Загрузить XML в DOM дерево, потом пройти по нему и найти нужный элемент. Или вопрос в чем то другом?

Автор: Cheloveck 8.7.2011, 17:27
xvr, тут лучше SAX, а не DOM.

DCamer, парсеры SAX работают на колбеках. Ты говоришь ему распарсить документ/файл/поток, он при нахождении каждого тега вызывает колбек и передаёт имя тега и список пар атрибут-значение. Тебе остаётся лишь дождаться нужного колбека и загрузить нужную инфу, после чего сказать парсеру остановиться. По сравнению с DOM SAX парсеры не требовательны к памяти, то есть ты сможешь обрабатывать файлы хоть по терабайту. И самому выискивать ничего не нужно, тебе всё на блюдечке принесут. Не знаю, есть ли а VCL SAX парсер, но http://www.xmlsoft.org/точно всё это умеет. Кроме того, у libxml есть http://libxmlplusplus.sourceforge.net/

Автор: DCamer 8.7.2011, 19:02
Цитата(xvr @  8.7.2011,  17:57 Найти цитируемый пост)
потом пройти по нему и найти нужный элемент

По значению атрибута? Суть в том, что ID собираются из самого XML-документа.
Цитата(Cheloveck @  8.7.2011,  18:27 Найти цитируемый пост)
По сравнению с DOM SAX парсеры не требовательны к памяти

Относительно требовательности, не суть важно. XML-документы больше 1 МБ в моём случае не бывают. smile 

Автор: xvr 8.7.2011, 19:47
Цитата(DCamer @  8.7.2011,  19:02 Найти цитируемый пост)
По значению атрибута?
Да
Цитата(DCamer @  8.7.2011,  19:02 Найти цитируемый пост)
Суть в том, что ID собираются из самого XML-документа.
Это чему то противоречит?
Цитата(DCamer @  8.7.2011,  19:02 Найти цитируемый пост)
По сравнению с DOM SAX парсеры не требовательны к памяти
Тогда уж вам больше подойдет StAX парсер (видел на sourceforge проект lsxml - очень маленький и простой a-la StAX парсер). У SAX довольно много писанины для подключения колбэков. Код с использованием DOM парсера получается компактнее



Автор: DCamer 8.9.2011, 21:17
К сожалению, не смог найти методы работы, как с SAX-, так и DOM-парсерами. smile  smile 

Автор: xvr 8.9.2011, 21:35
Цитата(DCamer @ 8.9.2011,  21:17)
К сожалению, не смог найти методы работы, как с SAX-, так и DOM-парсерами. smile  smile

Для DOM: Загружаете XML (функция XMLDocument() и метод Load()), потом перебираете все items верхнего уровня и ищите среди них item с тэгом Question. Проверяете у них атрибут id на требуемое значение

Автор: DCamer 8.9.2011, 21:41
Цитата(xvr @  8.9.2011,  22:35 Найти цитируемый пост)
Проверяете у них атрибут id на требуемое значение

В этом основная проблема, не могу понять как проверить атрибут этот.

Автор: xvr 9.9.2011, 12:28
Цитата(DCamer @  8.9.2011,  21:41 Найти цитируемый пост)
В этом основная проблема, не могу понять как проверить атрибут этот.

Код

_di_IXMLNode node = ...
int id = ...

if (node->NodeType ==ntElement &&  node->NodeName == "Question" && node->GetAttribute("id") == id)
 {
   ...
 }

Автор: DCamer 9.9.2011, 19:26
Цитата(xvr @  9.9.2011,  13:28 Найти цитируемый пост)
node->NodeType ==ntElement &&  node->NodeName == "Question" && node->GetAttribute("id") == id

Ошибка: 
Код

Ambiguity between '_fastcall operator Variant::bool() const' and '_fastcall operator Variant::__int64() const'


К тому же, окно выбора ID — модальное окно.

Автор: xvr 9.9.2011, 19:59
Цитата(DCamer @  9.9.2011,  19:26 Найти цитируемый пост)
Ошибка: 

Ну так приведите ему тип, что бы понял:
Код

__int64(node->GetAttribute("id")) == id


Цитата(DCamer @  9.9.2011,  19:26 Найти цитируемый пост)
К тому же, окно выбора ID — модальное окно.

Ну и что? В чем проблема передать id из этого окна?

Автор: DCamer 9.9.2011, 20:47
Странно, выбираю ID, но загружается первый Question.
Вот, листинг:
Код

// открытие файла //---------------------------------------------------
void __fastcall TForm1::N5Click(TObject *Sender)
{
   if (OpenDialog1->Execute())
    {
    AnsiString fname = ExtractFileName(OpenDialog1->FileName);
    Form1->Caption = fname + " — Title";
    AnsiString valbt;
    int n;
    _di_IXMLDocument XMLDoct = NewXMLDocument();
    try {
        XMLDoct->LoadFromFile(OpenDialog1->FileName);
        XMLDoct->Active=true;
        XMLDoct->Encoding="UTF-8";
        XMLDoct->Options=XMLDoct->Options << doNodeAutoIndent;
        IXMLNode *nodRootb= XMLDoct->DocumentElement;
        IXMLNode *nodElementb = nodRootb->ChildNodes->FindNode( "Question" );
        IXMLNode *nodEl = nodRootb->ChildNodes->FindNode( "Question" );
        if (nodElementb->NodeType ==ntElement && nodElementb->NodeName == "Question" && nodElementb->GetAttribute("id") == id ) {
            n=nodRootb->ChildNodes->Count;
            cbb1->Clear();
            Memo1->Clear();
            for (int i = 0; i < n; i++) {
                        nodEl = nodRootb->ChildNodes->Nodes[i];
                        AnsiString value= nodEl->GetAttribute("id");
                    cbb1->Items->Add(value);
                }
           valbt = nodElementb->GetAttribute("text");
           Memo1->Lines->Add(valbt);
           if (nodElementb->ChildNodes->Count == 1) {
             Edit1->Clear();
             Memo2->Clear();
                             if (nodElementb) {
                             IXMLNode *child1 = nodElementb->ChildNodes->Get(0);
                             AnsiString ch1 = child1->GetAttribute( "text" );
                                 if (child1->ChildNodes->Count == 2) {
                                   AnsiString ch2 = child1->GetAttribute( "nextQuestion" );
                                 }
                             Memo2->Lines->Add(ch1);
                             Edit1->Text = ch2;
                             }
             Memo3->Lines->Add(ch3);
             }
             twoans->Checked = true;
           }
           }
        }
       }
    __finally { delete XMLDoct;}
  }
}

Код

// при выборе //-------------------------------------------------------------
void __fastcall TForm1::cbb1Select(TObject *Sender)
{
    id = cbb1->SelText;
}

Автор: xvr 10.9.2011, 11:40
Ваш if (nodElementb->NodeType ==ntElement && nodElementb->NodeName == "Question" && nodElementb->GetAttribute("id") == id ) должен находится в цикле. Сейчас у вас извлекается первый же Question, и если так совпало, что ID у него соответствует, то он и загружается, а если ID не совпало, то ничего не меняется - т.е. остается первый загруженный (с прошлого раза)

Автор: DCamer 16.9.2011, 16:35
Цитата(xvr @  10.9.2011,  12:40 Найти цитируемый пост)
должен находится в цикле

Так он находится в цикле Try.

Автор: xvr 16.9.2011, 20:40
Цитата(DCamer @ 16.9.2011,  16:35)
Цитата(xvr @  10.9.2011,  12:40 Найти цитируемый пост)
должен находится в цикле

Так он находится в цикле Try.

Я вас неприятно обрадую, но try -это не цикл, это блок. Он выполняется только 1 раз

Автор: DCamer 17.9.2011, 18:06
Все варианты перепробывал, результат нулевой.

Автор: xvr 18.9.2011, 09:51
Код

        XMLDoct->LoadFromFile(OpenDialog1->FileName);
        XMLDoct->Active=true;
        IXMLNode *nodRootb= XMLDoct->DocumentElement;
        for(int i=0;i<nodRootb->ChildNodes->Count;++i)
         {
          IXMLNode *nodElementb = nodRootb->ChildNodes->Nodes[i];
          if (nodElementb->NodeType ==ntElement && nodElementb->NodeName == "Question" && nodElementb->GetAttribute("id") == id ) {
            ...
         }

Автор: DCamer 12.11.2011, 17:21
Спасибо! smile  Жаль, конечно, в комбо-боксе приходится дважды выбирать пункт, чтобы он загрузился.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)