Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка при работе с XML 
V
    Опции темы
Dom
Дата 22.7.2007, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Есть xml-файл, следующего содержания

Код

<?xml version="1.0" encoding="windows-1252"?>
<ISPs version="1.033">
    <ISP>
        <Name>AlphaTV +</Name>
        ...
    </ISP>
    <ISP>
        <Name>AlphaTV -</Name>
        ...
    </ISP>
    <ISP>
        <Name>Aries</Name>
        ...
    </ISP>
    <ISP>
        <Name>Aries +</Name>
        ...
    </ISP>
</ISPs>


Написал функцию DefineISPNames для извлечения значений нод 'Name' в StringList. Работает отлично.
Код

var   MainXMLDoc : IXMLDocument;
...
MainXMLDoc := TXMLDocument.Create(nil);
MainXMLDoc.NodeIndentStr := #9;
MainXMLDoc.Options := MainXMLDoc.Options + [doNodeAutoIndent];
...
MainXMLDoc.LoadFromFile(XMLFileName);
MainXMLDoc.Active := true;
...

function DefineISPNames : TStringList;
var
i : integer;
Node : IXMLNode;
begin
  Result := TStringList.Create;
  Result.Sorted := true;
  Node := MainXMLDoc.DocumentElement;
  for i := 0 to Node.ChildNodes.Count-1 do begin
    Result.Add(Node.ChildNodes[i].ChildNodes['Name'].NodeValue);
  end;
end;

После создаю новую ноду <ISP> и ее детей и добавляю ее в начало списка. Затем снова вызываю DefineISPNames. Но в этот раз она считывает только одну первую ноду и на второй ноде (i =1) выдает ошибку в строке 20 Result.Add(Node.ChildNodes[i].ChildNodes['Name'].NodeValue)
Ошибка вот какая -  Project wsnake.exe raised exception class EOleException with message 'This operation can not be performed with a Node of type PCDATA'. Process stopped. Use Step or Run to continue.
Что это за тип ноды PCDATA? Что-то ничего не могу найти про это ни в хелпах ни в инете.

Кстати, если после добавления новой ноды <ISP> сохранить xml-файл, то в нем сохраняются все ноды, и добавленная и старые, и все на своих местах. Т.е. структура документа правильная.

Надеюсь на вашу помощь. smile

Это сообщение отредактировал(а) Dom - 22.7.2007, 11:46
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



Цитата

После создаю новую ноду <ISP> и ее детей и добавляю ее в начало списка. Затем снова вызываю DefineISPNames. Но в этот раз она считывает только одну первую ноду и на второй ноде (i =1) выдает ошибку в строке 20 Result.Add(Node.ChildNodes[i].ChildNodes['Name'].NodeValue)


Так может ты неправильно её создаешь (ноду). Прогони построчно через debuger и посмотри как изменяется твой документ 
после добавления в него новой ноды. Именно через debuger, а не сохраняя документ.

Кстати, а если сохраненный документ с новой нодой, попытаться прогнать твоей функцией, тоже вылетит такая же ошибка на том же месте?

PCDATA - анализируемые символьные данные или данные, которые обычно отображаются в браузере.

P.s.: Раз уж приводишь код, так приводи весь, чтобы можно было самому погонять программу smile 

Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 18:11


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Цитата(ALeXandrK @ 26.7.2007,  18:01)
Кстати, а если сохраненный документ с новой нодой, попытаться прогнать твоей функцией, тоже вылетит такая же ошибка на том же месте?

Нет, если сохраненный документ снова открыть и считывать сожержимое нод этой функцией, то ошибки не возникает, и все ноды в т.ч. и новая отображаются правильно в создаваемом списке. Даже был такой топорный вариант - пересохранять файл, каждый раз после добавления ноды. Но рука до сих пор не поднялась на подобное. smile

С debuger'ом попробую разобраться, раньше с ним не работал.  Но спасибо за подсказку.

Код сейчас приведу.

У меня подозрение на несоместимость данных, т.е. я пытаюсь загнать в стринг содержимое ноды, а там как-будто не строка содержится. Может какое-то преобразование данных нужно...
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



Цитата

У меня подозрение на несоместимость данных, т.е. я пытаюсь загнать в стринг содержимое ноды, а там как-будто не строка содержится. Может какое-то преобразование данных нужно...

Самое простое, чтобы проверить, это перевести все в тип String и сохранять и читать его как String.
Если это не поможет, значит ошибка не в типе.

Нет... тут точно нужно debugerом гнать. 

Цитата

С debuger'ом попробую разобраться, раньше с ним не работал.

Тем более нельзя упускать такой шанс научиться им пользоваться - это все-равно рано или поздно
придется делать. А сложного там ничего нет... так что дерзай  smile 

P.s.: Если уж с нодами разобрался, то дебагер - это плёвое дело smile 

Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 19:32


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Код

var   MainXMLDoc : IXMLDocument;

//открытие xml-файла
procedure TForm1.XML1Click(Sender: TObject);
var
ISPNameList : TStringList;
begin
  OpenDialog3.Title := 'Open XML file';
  OpenDialog3.DefaultExt := 'xml';
  OpenDialog3.Filter := 'Xml files (*.xml)|*.xml|All files (*.*)|*.*';
  if OpenDialog3.Execute then begin
    MainXMLFileName := OpenDialog3.FileName;
    MainXMLDoc := TXMLDocument.Create(nil);
    MainXMLDoc.NodeIndentStr := #9;
    MainXMLDoc.Options := MainXMLDoc.Options + [doNodeAutoIndent];
    MainXMLDoc.LoadFromFile(MainXMLFileName);
    MainXMLDoc.Active := true;
    ISPNameList := DefineISPNames;    //тут ошибки не возникает
  end;
end;

//вызов процедуры добавления ноды
//на AddNewISPForm расположены Edit'ы и CheckBox'ы
//значения которых и надо добавить в новую ноду
procedure TForm1.Button8Click(Sender: TObject);
begin
  AddNewISPForm := TAddNewISPForm.Create(Self);
  if AddNewISPForm.ShowModal = mrOK then begin
    AddNewISPNodeToXML;
  end;
end;

//функция которая возвращает список значений нод Name
function DefineISPNames : TStringList;
var
i : integer;
Node : IXMLNode;
begin
  Result := TStringList.Create;
  Result.Sorted := true;
  Node := MainXMLDoc.DocumentElement;
  for i := 0 to Node.ChildNodes.Count-1 do begin
//в этом месте возникает ошибка при вызове функции из AddNewISPNodeToXML
//при i=1, т.е. при попытке прочесть вторую ноду в списке
//хотя новая нода добавляется первой в списке и ее данные считываются без проблем
    Result.Add(Node.ChildNodes[i].ChildNodes['Name'].NodeValue);  end;
end;

//процедура добавления новой ноды и ее содержимого
procedure AddNewISPNodeToXML;
var
ISPNode : IXMLNode;
ISPNameList : TStringList;
begin
    MainXMLDoc.DocumentElement.AddChild('ISP',0);    //добавляю ISP ноду в начало списка
    ISPNode := MainXMLDoc.DocumentElement.ChildNodes[0];
    ISPNode.AddChild('Name').NodeValue := NameEdit.Text;
    ISPNode.AddChild('Description').NodeValue := DescriptionEdit.Text;
    ISPNode.AddChild('Prefix').NodeValue := PrefixEdit.Text;
    ISPNode.AddChild('MinShare').NodeValue := StrToInt64(MinShareEdit.Text);
    if MinShareCheckBox.State = cbChecked then
      ISPNode.ChildNodes['MinShare'].Attributes['enable'] := 'true';

    MainXMLDoc.SaveToFile(MainXMLFileName);
    ISPNameList := DefineISPNames;  //тут возникает ошибка внутри самой функции
end;


Вот собственно все необходимые компоненты. Надеюсь комментарии помогут разобраться в деталях.

Добавлено через 1 минуту и 4 секунды
Цитата(ALeXandrK @ 26.7.2007,  19:31)
Самое простое, чтобы проверить, это перевести все в тип String и сохранять и читать его как String.
Если это не поможет, значит ошибка не в типе.

Уже пробовал. Действительно ошибка не в типе.

Добавлено через 7 минут и 10 секунд
Цитата

Тем более нельзя упускать такой шанс научиться им пользоваться - это все-равно рано или поздно
придется делать. А сложного там ничего нет... так что дерзай   

P.s.: Если уж с нодами разобрался, то дебагер - это плёвое дело  

Я не совсем уж новичок в программировании. Но вот с дебагером еще не сталкивался. Займусь.  smile 
А с нодами разобраться несложно было. Тем более тут на форуме полно дельных советов есть и толковых кусочков кода. smile 

Это я решил для нашего хаба по-быстрому написать прогу для редактирования всех настроек, чтобы не руками лазить каждый раз. Однако процесс затянулся. smile 
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 20:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



А что за тип такой TAddNewISPForm?
Я понимаю, что это форма, а в чём её задача?

Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 20:03


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Не совсем верный код запостил для процедуры AddNewISPNodeToXML
Там надо добавить в начало строку
Код

with AddNewISPForm do begin


Более точная процедура бцдет выглядеть так.
Код

procedure AddNewISPNodeToXML;
var
ISPNode : IXMLNode;
ISPNameList : TStringList;
begin
  with AddNewISPForm do begin
    MainXMLDoc.DocumentElement.AddChild('ISP',0);    //добавляю ISP ноду в начало списка
    ISPNode := MainXMLDoc.DocumentElement.ChildNodes[0];
    ISPNode.AddChild('Name').NodeValue := NameEdit.Text;
    ISPNode.AddChild('Description').NodeValue := DescriptionEdit.Text;
    ISPNode.AddChild('Prefix').NodeValue := PrefixEdit.Text;
    ISPNode.AddChild('MinShare').NodeValue := StrToInt64(MinShareEdit.Text);
    if MinShareCheckBox.State = cbChecked then
      ISPNode.ChildNodes['MinShare'].Attributes['enable'] := 'true';

    MainXMLDoc.SaveToFile(MainXMLFileName);
    ISPNameList := DefineISPNames;  //тут возникает ошибка внутри самой функции
  end;
end;


Сорри. Надеюсь это не фатальная ошибка. И так ясно что присваиваются значения полей Edit.

Добавлено через 1 минуту и 28 секунд
AddNewISPForm это форма, на которой расположены Edit'ы и CheckBox'ы, значения которых и надо добавить в новую ноду
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



Для полного счастья прикрепи свой xml файлик smile 

Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 20:15


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Цитата(ALeXandrK @ 26.7.2007,  20:15)
Для полного счастья прикрепи свой xml файлик smile

Легко. smile 
Только не очень удивляйся всем полям в файле. Просто сейчас я сократил для простоты экспериментов процедуру добавления и отключил добавление всех дочерних нод, оставил только несколько.

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  od.rar 0,44 Kb
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



Добавление проверил. Все верно... переходим на функцию DefineISPNames.
Странно, но 
Код

  for i := 0 to Node.ChildNodes.Count-1 do begin
  Result.Add(Node.ChildNodes[i].ChildNodes['Name'].NodeValue);


При открытии это цикл выполняется дважды (у меня две ноды). Т.е. всё верно,
но
Код

  for i:=0 to ISPNameList.Count-1 do
  ShowMessage(ISPNameList.ValueFromIndex[i]);


Показывает, что в списке только один элемент. Ерунда какая-то smile 

Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 21:00


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Стоп. А куда ты последний цикл вставлял?

Я выводил значения ISPNameList в ListBox вот таким образом
Код

procedure FillListBoxWithISPName(const NameList: TStringList; var ListBox: TListBox);
var
i : integer;
begin
  ListBox.Clear;
  if ListBox.Name = 'RemoveSectionListBox' then
    ListBox.AddItem('All',nil);
  for i := 0 to NameList.Count-1 do begin
    ListBox.AddItem(NameList[i],nil);
  end;
end;
...
FillListBoxWithISPName(ISPNameList,ListBox1);
и никаких проблем не возникало, все ноды на месте...

Добавлено через 2 минуты и 41 секунду
На строки 6 и 7 не обращай внимания. Это я добавляю первым элементом строку с надписью All в один из листбоксов.
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



Лохонусля... там все тоже ок smile 


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Учусь пока обращатсья с дебаггером...
Кстати у меня Делфи 7. Уже не знаю на что и думать.
PM MAIL   Вверх
ALeXandrK
Дата 26.7.2007, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 342
Регистрация: 31.1.2007
Где: Санкт-Петербург

Репутация: 1
Всего: 6



 smile Ура... нашел. Вот эти строчки нужно убрать, тогда все работает великолепно smile 
Код

    MainXMLDoc.NodeIndentStr := #9;
    MainXMLDoc.Options := MainXMLDoc.Options + [doNodeAutoIndent];


Из-за этих строк и происходит билиберда, если они очень нужны, то ищи что-то в эту тему...
видимо открытый файл нужно обновлять или что-то в этом роде, т.к. после вставки новых нод
XML вообще пуст (это в памяти - можешь убедиться через дебагер smile ). Потому и ошибка вылетает.



Это сообщение отредактировал(а) ALeXandrK - 26.7.2007, 21:42


--------------------
Богат не/ни тот, у кого много, а тот, кому хватает
PM WWW   Вверх
Dom
Дата 26.7.2007, 21:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 7.8.2005

Репутация: 3
Всего: 4



Шаман!  smile
Благодарю за помощь! Что-нибудь уже дальше придумаем.

Но учиться дебагингу все равно надо. Это как - купишь рыбу, будешь сыт день. Научишься ловить...  smile 

К сожалению репутацию добавить не могу. Поэтому еще раз поблагодярю за то, что помог разобраться.

Это сообщение отредактировал(а) Dom - 26.7.2007, 21:53
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0551 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.