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


Автор: DCamer 25.11.2010, 16:45
Как сделать чтение XML-документа, а именно опций узлов:
Код

<rootnode>
    <subnode option="test">
        <subsubnode option1="test1" option2="subtest" option3="1" option4="1" option5="1"/>
        <subsubnode option1="test3" option2="subtest"/>
    </subnode>
</rootnode>

Про встроенную компоненту TXMLDocument в курсе, но не знаю как с компонентой работать.

Автор: bsa 25.11.2010, 16:47
http://lmgtfy.com/?q=TXMLDocument знает и готов поделиться!

Автор: DCamer 25.11.2010, 16:53
В пресловутом гугле решений под C++Builder практически нет, а если и есть, то не то, что нужно.

Автор: bsa 25.11.2010, 17:12
http://forum.developing.ru/showthread.php?2289-TXMLDocument-C-Builder

Автор: DCamer 25.11.2010, 17:25
У меня выдаёт последний код, что какая-то ошибка на строке 1, видимо речь о XML-файле:
Код

First chance exception at $7C812AFB. Exception class EDOMParseError with message
'Системная ошибка: -2146697210.

Line: 0
'.
Process smee.exe (416)



Автор: DCamer 25.11.2010, 18:46
Вот что собственно надо:
http://s2.itrash.ru/idb/e20d3a3d54f79ff3494cfbc937f6fdcb/omaterialeffects.png.htm
Да, кстати в XML-файле нету этого:
Код

<?xml version="1.0" encoding="iso-8859-1" ?>

Автор: bsa 25.11.2010, 19:06
А если добавить эту строку, будет исключение?
Кстати, обрати внимание, что по приведенной ссылке работа с TXMLDocument была внутри блока try{}catch, думаю, неспроста.

Автор: DCamer 25.11.2010, 21:28
Эта ошибка - нет, но появляется новая ошибка:
Код

Warning: Invalid pointer operation

Автор: bsa 27.11.2010, 11:12
DCamer, и в каком месте появляется? Пройдись отладчиком! Тут телепатов нет.

Автор: DonPager 7.12.2010, 01:09
DCamer, ... и укажи версию билдера (в ХЕ немножко поменялся код для хмл)

Автор: DCamer 10.1.2011, 17:42
DonPager, версия билдера у меня в подписи. smile 

Автор: DCamer 10.1.2011, 18:12
bsa, отладчик при Break ссылается на System.pas:
Код

procedure TObject.FreeInstance;
begin
  CleanupInstance;
  _FreeMem(Self);        // курсор переходит на эту строку
end;

Автор: Isko 10.1.2011, 18:39
Могу скинуть кусок проги где у меня происходит чтение узлов и значенийю
Правда у меня не опции а всего лишь одно значение для каждого узла.

Автор: DCamer 10.1.2011, 18:55
Isko, скинь коль не жалко. smile 

Автор: DCamer 10.1.2011, 20:28
Всем спасибо, все свободны.  smile 
Код

      AnsiString value,nm;
    int n;
    _di_IXMLDocument XMLDocument = NewXMLDocument();
    try {
        XMLDocument->XML->Text="<SurfaceTypes><SurfaceType name=\"mat_oil_drops\"></SurfaceType></SurfaceTypes>";
        XMLDocument->Active=true;
        XMLDocument->Encoding="UTF-16";
        XMLDocument->Options=XMLDocument->Options << doNodeAutoIndent;
        IXMLNode *nodRoot= XMLDocument->DocumentElement;
        IXMLNode *nodElement;
        n=nodRoot->ChildNodes->Count;
        for (int i = 0; i < n; i++) {
            nodElement = nodRoot->ChildNodes->Nodes[i];
            value= nodElement->GetAttribute("name");
            nm = nodElement->GetNodeName();
            Edit3->Text = value;
        }
    }
    __finally { delete XMLDocument;}

Автор: DCamer 10.1.2011, 22:02
А как считать XML-файл, такого вида, который создаёт MS Office?

Автор: oldcode 10.1.2011, 23:45
Цитата(DCamer @ 10.1.2011,  22:02)
А как считать XML-файл, такого вида, который создаёт MS Office?

что ? нет ответа ? так ты же сам сказал : 
Цитата(DCamer)
Всем спасибо, все свободны.
 - что звучало довольно таки , как бы это мягче сказать, не красиво.

Автор: DCamer 11.1.2011, 14:01
oldcode, что-то я не помню такого, чтоб в течении часа отвечали. smile 

Автор: oldcode 12.1.2011, 12:00
уж который час пошел...

Автор: DCamer 12.1.2011, 13:28
Уж который раз я так пишу...

Автор: oldcode 12.1.2011, 14:07
Цитата(DCamer)
Уж который раз я так пишу...
 "А Германа все нет..." ( (С) А. С. Пушкинд.)

Добавлено @ 14:12
Цитата(DCamer @ 10.1.2011 @   22:02)
А как считать XML-файл, такого вида, который создаёт MS Office?
 - это ты про .docx ?
Если да , то переименуй .docx в .hml или в другое любое немыслимое расширение ;) и нажми Key(13)  smile ...

Автор: DCamer 27.2.2011, 23:29
Если вам нечего сказать по делу, не говорите ничего.
Но я говорил про XML-файл, который не имеет стандартной структуры тегов, а состоит из Workbook.

Автор: xvr 28.2.2011, 17:33
Цитата(DCamer @ 27.2.2011,  23:29)
Но я говорил про XML-файл, который не имеет стандартной структуры тегов, а состоит из Workbook.

С какого перепугу он вдруг 'не имеет стандартной структуры тегов'? Вполне стандартные xml файлы (и много)

Автор: DCamer 28.2.2011, 22:08
В обычной структуре нет такого:
Код

<Cell ss:StyleID="s37"><Data ss:Type="String">текст в ячейке</Data></Cell>

И компонент TXMLDocument не читает его вообще, а если исходить из вашей логики, то оный должны его считывать нормально.

Автор: xvr 28.2.2011, 22:57
Цитата(DCamer @ 28.2.2011,  22:08)
В обычной структуре нет такого:
Код

<Cell ss:StyleID="s37"><Data ss:Type="String">текст в ячейке</Data></Cell>


Нормальный фрагмент с xml-namespace'ами
Цитата

И компонент TXMLDocument не читает его вообще, а если исходить из вашей логики, то оный должны его считывать нормально.
Должен. Если не читает - то это проблема TXMLDocument'а. Возможно он не поддерживает xml namespace'ы. Тогда возьмите нормальный парсер (MSXML например)

Автор: DCamer 6.3.2011, 14:46
Да-с, знать бы откуда его взять.

Автор: xvr 6.3.2011, 19:43
Цитата(DCamer @ 6.3.2011,  14:46)
Да-с, знать бы откуда его взять.

Из IE вестимо. Читать http://msdn.microsoft.com/en-us/library/ms763742%28v=VS.85%29.aspx и особенно http://msdn.microsoft.com/en-us/library/ms766487%28v=VS.85%29.aspx

Автор: DCamer 10.4.2011, 14:00
Предположим есть такой XML:
Код

<Column ss:StyleID="s21" ss:AutoFitWidth="0" ss:Width="192.75" ss:Span="2"/>
<Row ss:AutoFitHeight="0" ss:StyleID="s29">
  <Cell ss:StyleID="s37"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell ss:StyleID="s28"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell ss:StyleID="s26"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell><Data ss:Type="String">текст в ячейке</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0" ss:StyleID="s24">
  <Cell ss:StyleID="s37"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell ss:StyleID="s28"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell ss:StyleID="s26"><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell><Data ss:Type="String">текст в ячейке</Data></Cell>
  <Cell><Data ss:Type="String">текст в ячейке</Data></Cell>
</Row>

Как все их вгрузить в ListBox?
Пробовал такой код:
Код

      AnsiString values,nms,vals;
    _di_IXMLDocument XMLDoc = NewXMLDocument();
    try {
        XMLDoc->LoadFromFile(fp+"\\s.xml");
        XMLDoc->Active=true;
        XMLDoc->Encoding="UTF-16";
        XMLDoc->Options=XMLDoc->Options << doNodeAutoIndent;
        IXMLNode *nodRoot= XMLDoc->DocumentElement;
        IXMLNode *nodElement;
        n=nodRoot->ChildNodes->Count;
        for (int i = 0; i < n; i++) {
            nodElement = nodRoot->ChildNodes->Nodes[3]->ChildNodes->Nodes[1]->ChildNodes->FindNode("Row")->ChildNodes->Nodes[i]->ChildNodes->FindNode("Data");
            nms = nodElement->GetNodeValue();
            eff->Items->Add(nms);
            }
    }
    __finally { delete XMLDoc;}

Но, в данном случае, он находит лишь первый узел «Row», и считывает с него данные, но нужно чтобы считывал со всех узлов «Row».

Автор: xvr 10.4.2011, 18:28
Цитата(DCamer @  10.4.2011,  14:00 Найти цитируемый пост)
            nodElement = nodRoot->ChildNodes->Nodes[3]->ChildNodes->Nodes[1]->ChildNodes->FindNode("Row")->ChildNodes->Nodes[i]->ChildNodes->FindNode("Data");

Ой, мама, роди меня обратно!  smile При разборе XML крайне не рекомендуется пользоваться абсолютными индексами в узлах. Формат XML достаточно гибок, что бы добавить парочку узлов, и все ваши индексы поедут  smile 
В вашем случае напрашивается использование XPath. 
Там есть нечто называемое IXMLNode::TransformNode - это XSLT трансформация. Можете воспользоваться ею

Цитата(DCamer @  10.4.2011,  14:00 Найти цитируемый пост)
Но, в данном случае, он находит лишь первый узел «Row»

Еще бы, вы же ему явно сказали 
Цитата

nodRoot->ChildNodes->Nodes[3]->ChildNodes->Nodes[1]->ChildNodes->FindNode("Row")
это явно выделенный 1 узел Row

Автор: DCamer 10.4.2011, 21:14
Цитата(xvr @  10.4.2011,  19:28 Найти цитируемый пост)
nodRoot->ChildNodes->Nodes[3]->ChildNodes->Nodes[1]->ChildNodes->FindNode("Row")
это явно выделенный 1 узел Row

Нет. 3 - это Worsheet, 1 - это Table (обычная структура). Далее же идет обращение к Row (ChildNodes->FindNode("Row")).

Автор: xvr 11.4.2011, 13:05
Цитата(DCamer @  10.4.2011,  21:14 Найти цитируемый пост)
Далее же идет обращение к Row

Угу, к ОДНОМУ row, а у вас их несколько.

Автор: DCamer 30.4.2011, 16:42
Не увидел я XSLT-трансформацию негде, к сожалению...

Автор: srt 1.5.2011, 01:23
http://www.sitemaps.org/schemas/sitemap/0.9
ещё можно яндексовый хмл посмотреть
но луче сётки w3.org

Автор: xvr 1.5.2011, 11:00
Цитата(DCamer @  30.4.2011,  16:42 Найти цитируемый пост)
Не увидел я XSLT-трансформацию негде, к сожалению... 

В MSDN тоже не было? Там довольно подробно расписано. ( http://msdn.microsoft.com/en-us/library/ms765388%28VS.85%29.aspx )

В вашем случае такой xsl файл :
Код

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="Cell">
        <item>
          <xsl:value-of select="Data"/>
        </item>
  </xsl:template>
</xsl:stylesheet>
Извлечет все Data вложенные в Cell и сделает из них плоский список xml тэгов item
Вам надо загрузить этот xsl файл в XMLDocument а потом подать его корень в nodRoot->TransformNode
На выходе получите XML документ из одних <item> ..</item>

Автор: srt 1.5.2011, 14:04
мастдай форева
хоть его все и хают - но там самая подробная инфа лежит

Автор: DCamer 1.5.2011, 15:51
Цитата(xvr @  1.5.2011,  12:00 Найти цитируемый пост)
Вам надо загрузить этот xsl файл в XMLDocument а потом подать его корень в nodRoot->TransformNode

Странно, вываливается ошибка:
Код

[BCC32 Error] sme.cpp(85): E2285 Could not find a match for 'IXMLNode::TransformNode(IXMLNode *)'

Код:
Код

        XMLDoc->LoadFromFile(fp+"\\xmlfile.xml");
        XMLDoc->Active=true;
        XSLDoc->LoadFromFile(fp+"\\xmlfile.xsl");
        XSLDoc->Active=true;
        IXMLNode *nodRoot= XMLDoc->DocumentElement;
        IXMLNode *xslnodRoot= XSLDoc->DocumentElement;
        nodRoot->TransformNode(xslnodRoot); // строка 85

Да, кстати, относительно XSLT-трансформации: оная позволит записать изменения в XML-файл?

Автор: srt 1.5.2011, 20:59
блин просто напиши echo 'hello world';
если чото получица - напиши:О)

Добавлено через 1 минуту и 25 секунд
вы чо пацаны - читать разучились??
я в лёгком нифигасебе ..

Добавлено через 11 минут и 15 секунд
расслабься - ХМЛ не при делах
просто ты со своим провом не до... говорился  :О)

Добавлено через 11 минут и 54 секунды
на самом деле достаточно просто масива ..

Автор: DCamer 1.5.2011, 23:44
Цитата(srt @  1.5.2011,  21:59 Найти цитируемый пост)
на самом деле достаточно просто масива .. 

На самом деле массив идёт дальше, т.к. в массиве идёт само заполнение компонент содержимым XML-файла.

Цитата(srt @  1.5.2011,  21:59 Найти цитируемый пост)
блин просто напиши echo 'hello world';

Ну вот и пиши код PHP в приложении C++.  smile

Автор: srt 2.5.2011, 01:36
запросто
хмл это разбор в
а потом разбор из
массив проще
хоть си хоть пыхыпы
..

Автор: xvr 2.5.2011, 09:49
Цитата(DCamer @  1.5.2011,  15:51 Найти цитируемый пост)
Странно, вываливается ошибка:

Ему еще надо подать куда выводить:
Код

    virtual void __fastcall TransformNode(const _di_IXMLNode stylesheet, WideString &output) = 0 /* overload */;
    virtual void __fastcall TransformNode(const _di_IXMLNode stylesheet, const _di_IXMLDocument output) = 0 /* overload */;

Цитата(DCamer @  1.5.2011,  15:51 Найти цитируемый пост)
Да, кстати, относительно XSLT-трансформации: оная позволит записать изменения в XML-файл?

Угу, 2я разновидность вызова

Автор: DCamer 9.5.2011, 20:54
Цитата(xvr @  1.5.2011,  12:00 Найти цитируемый пост)
На выходе получите XML документ из одних <item> ..</item>

А как впоследствии все эти итемы вгрузить в ListBox? Что не пытаюсь сделать — везде та же структура остаётся.

Автор: xvr 9.5.2011, 22:27
Цитата(DCamer @  9.5.2011,  20:54 Найти цитируемый пост)
А как впоследствии все эти итемы вгрузить в ListBox?

Обойти как обычный (но одноуровневый) XMLDocument

Цитата(DCamer @  9.5.2011,  20:54 Найти цитируемый пост)
Что не пытаюсь сделать — везде та же структура остаётся.

Что то не так делаете - покажите код

Автор: DCamer 10.5.2011, 14:41
Цитата(xvr @  9.5.2011,  23:27 Найти цитируемый пост)
Что то не так делаете - покажите код

Код

      AnsiString values,nms,vals;
      WideString nnm;
    _di_IXMLDocument XMLDoc = NewXMLDocument();
    _di_IXMLDocument XMLDocbn = NewXMLDocument();
    try {
        XMLDoc->LoadFromFile(fp+"\\MaterialEffects.xml");
        XMLDoc->Active=true;
        XMLDoc->Options=XMLDoc->Options << doNodeAutoIndent;
        XMLDocbn->LoadFromFile(fp+"\\MaterialEffects.xsl");
        XMLDocbn->Active=true;
        XMLDocbn->Options=XMLDocbn->Options << doNodeAutoIndent;
        IXMLNode *nodRoot= XMLDoc->DocumentElement;
        IXMLNode *xslnodRoot= XMLDocbn->DocumentElement;
        nodRoot->TransformNode(xslnodRoot, XMLDoc);
        IXMLNode *nodTable;
        IXMLNode *nodElement;
        n=nodRoot->ChildNodes->Count;
        for (int i = 0; i < n; i++) {
            nodElement = nodRoot->ChildNodes->Nodes[i];
            nnm = nodElement->GetText();
            Memo1->Lines->SetText(WideString(nms).c_bstr());
            }
    }

Автор: xvr 10.5.2011, 17:08
Цитата(DCamer @  10.5.2011,  14:41 Найти цитируемый пост)
nodRoot->TransformNode(xslnodRoot, XMLDoc);

Неправильно. 2м параметром надо подать чистый XMLDoc, в него и будут занесены результаты трансформации

Автор: DCamer 6.6.2011, 22:27
Интересно, и как все эти item вгрузить?

Автор: xvr 7.6.2011, 12:29
Цитата(DCamer @ 6.6.2011,  22:27)
Интересно, и как все эти item вгрузить?

Ну собственно так, как вы и грузили - перебором элементов в Document'е. Только вам не придется заниматься сканированием иерархии Document'а - они все будут лежать прямо в корне

Автор: DCamer 7.6.2011, 20:16
Перебор работает, и почему, то пишет List index out of bounds (3), он что ли ищет четвёртый узел...
Код

        XMLDoct->LoadFromFile(Form1->OpenDialog1->FileName);
        XMLDoct->Active=true;
        XMLDoct->Encoding="UTF-8";
        XMLDoct->Options=XMLDoct->Options << doNodeAutoIndent;
        IXMLNode *nodRoot= XMLDoct->DocumentElement;
        IXMLNode *nodElement = nodRoot->ChildNodes->FindNode( "Question" );
        if ( nodElement ) {
        for (int i = 0; i < n; i++) {
                nodElement = nodRoot->ChildNodes->Nodes[i];
                value= nodElement->GetAttribute("id");
                ListBox1->Items->Add(value);
                }
            }

А трансформация, почему, то вызывает «Access violation at address 00459981 in module 'smee.exe'. Write of address 0053378D.»
Код

      AnsiString values,nms,vals,nnm;
    _di_IXMLDocument MatEff = NewXMLDocument();
    _di_IXMLDocument MatEffXSL = NewXMLDocument();
    _di_IXMLDocument Transform = NewXMLDocument();
    try {
        MatEff->LoadFromFile(fp+"\\MaterialEffects.xml");
        MatEff->Active=true;
        MatEff->Options=MatEff->Options << doNodeAutoIndent;
        MatEffXSL->LoadFromFile(fp+"\\MaterialEffects.xsl");
        MatEffXSL->Active=true;
        MatEffXSL->Options=MatEffXSL->Options << doNodeAutoIndent;
        Transform->Active=true;
        IXMLNode *nodRoot= MatEff->DocumentElement;
        IXMLNode *xslnodRoot= MatEffXSL->DocumentElement;
        nodRoot->TransformNode(xslnodRoot, Transform);
        Transform->Options=MatEffXSL->Options << doNodeAutoIndent;
        IXMLNode *nodtRoot= Transform->DocumentElement;
        IXMLNode *nodTable;
        IXMLNode *nodElement;
        n=nodRoot->ChildNodes->Count;
        for (int i = 0; i < n; i++) {
            nodElement = nodtRoot->ChildNodes->Get(i);
            nnm = nodElement->GetNodeName();
            eff->Items->Add(nnm);
            }
    }
    __finally { delete MatEff; MatEffXSL; Transform;}

Автор: xvr 7.6.2011, 22:28
Цитата(DCamer @  7.6.2011,  20:16 Найти цитируемый пост)
Перебор работает, и почему, то пишет List index out of bounds (3), он что ли ищет четвёртый узел...

Видимо да. А чему у вас равен n?

Цитата(DCamer @  7.6.2011,  20:16 Найти цитируемый пост)
А трансформация, почему, то вызывает «Access violation at address 00459981 in module 'smee.exe'. Write of address 0053378D.»

На какой строке?

Автор: DCamer 8.6.2011, 18:36
Цитата(xvr @  7.6.2011,  23:28 Найти цитируемый пост)
Видимо да. А чему у вас равен n?

Что-то я про эту переменную забыл, исправил. Спасибо. smile
Цитата(xvr @  7.6.2011,  23:28 Найти цитируемый пост)
На какой строке?

Проверка точкой останова указала на:
Код

nnm = nodElement->GetNodeName();

Автор: xvr 8.6.2011, 21:59
У вас счетчик извлекается из nodRoot, а элементы из nodtRoot
Кроме того, то  xslt, который я приводил, кладет элементы прямо в сам XMLDocument, а не в корневой узел. Т.е. он формирует XML-Fragment, а не нормальный XML-Document. Я не знаю, как будет себя чувствовать IXMLDocument с такими данными. Подправьте MaterialEffects.xsl

Автор: DCamer 8.6.2011, 22:41
Цитата(xvr @  8.6.2011,  22:59 Найти цитируемый пост)
У вас счетчик извлекается из nodRoot, а элементы из nodtRoot

Это я знаю, но результатов нет.
Цитата(xvr @  8.6.2011,  22:59 Найти цитируемый пост)
Подправьте MaterialEffects.xsl

Коим образом? Добавив корневой элемент? Не помогает.

Автор: DCamer 15.2.2012, 17:52
Подскажите, пожалуйста, каким образом сохранить XML-файл перебором? То есть, есть куча узлов в двух ListView, содержимое каждого ListView добавляется в свой узел в XML-файле. Структура выходного XML-файла такова:
Код

<combinode>
   <treeview1>Узел 1 TreeView 1</treeview1>
   <treeview2>Узел 1 TreeView 2</treeview2>
</combinode>
<combinode>
   <treeview1>Узел 2 TreeView 1</treeview1>
   <treeview2>Узел 2 TreeView 2</treeview2>
</combinode>

Автор: xvr 16.2.2012, 09:19
Цитата(DCamer @  15.2.2012,  17:52 Найти цитируемый пост)
 Структура выходного XML-файла такова:

Сделайте этому всему корневой узел и сохраняйте. 
Для добавления элемента используется метод типа addElement (или newElement - не помню точно)

Автор: DCamer 17.2.2012, 20:27
Цитата(xvr @  16.2.2012,  10:19 Найти цитируемый пост)
Для добавления элемента используется метод типа addElement (или newElement - не помню точно)

А если программно надо добавить ряд статических узлов? Например:
Код

<Root>
   <xs:schema>
       // любая часть
   </xs:schema>
   <combinode>
      <treeview1>...</treeview1>
      <treeview2>...</treeview2>
   </combinode>
   <combinode>
      <treeview1>...</treeview1>
      <treeview2>...</treeview2>
   </combinode>
<Root>


То есть, добавить рут не беда, но надо всю xs:schema, программно по нодам создавать как-то муторно.

Вот так создать рут не получается:
Код

    IXMLNode *nodRoot = xmldc->DocumentElement;
    _di_IXMLNode nodElement = xmldc->CreateElement("Root", "");
        nodRoot->ChildNodes->Add(nodElement);

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