Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5

Ошибка из ниоткуда при работе с XML в Delphi

30.08.2010, 03:02. Показов 1954. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Краткая предыстория. Надо мне было создать универсальную языковую технологию для обычных приложений и для веба. Из всех возможных вариантов форматов хранения данных был естественно выбран XML. Если вкратце, то структура языкового документа такова

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="windows-1251"?>
<xlng version="1.0">
  <language name="SomeName1" id="XX" default="X">
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
  </language>  <language name="SomeName2" id="XX" default="X">
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
    <component name="CompName" type="CompType" hint="Something">Something</component>
  </language>
...
</xlng>
CompName - имя компонента. Должно соответствовать реальному имени в приложении.
CompType - Тип компонента. Не будем на этом заостряться пока.
Something - Какой либо текст до 254 символов.
SomeName1, SomeName2 - человеко-понятные имена языков.
XX - Идентификатор языка согласно спецификации ISO-3166-1-alpha-2
X - 1 или 0

Вроде бы всё понятно. Создаём документ по этим правилам и, в зависимости от того, веб или десктоп, тем или образом парсим. Библиотека для работы с этой технологией была написана. Но не тут-то было...

Итак. Описание "дефектной" функции:
Pascal
1
function xlng_translate_statictext(LangDoc: TXMLDocument; Component: TStaticText; Language: ShortString): byte; stdcall;
Функция переводит Caption компонента TStaticText. В качестве входных параметров берутся языковой документ (LangDoc), собственно сам статический текст (Component) и идентификатор языка (Language).
Теперь фрагмент кода в обработчике OnCreate формы:
Pascal
1
2
3
4
  xlng_translate_statictext(XMLDocument,stt_key,'RU');
  xlng_translate_statictext(XMLDocument,stt_value,'RU');
  xlng_translate_statictext(XMLDocument,stt_save,'RU');
  xlng_translate_statictext(XMLDocument,stt_open,'RU');
Суть ошибки: вылетает стандартное окошко "с-предложением-отправить-отчёт", притом при закрытии приложения. НО! Что удивительно, если закомментировать последнюю строку или поменять местами скажем с предыдущей, этого не происходит. Сразу скажу, что в библиотеке, из которой и берётся, собственно, функция, нет ни глобальных переменных, ни объектов, вобщем подозрения на некий глобальный счётчик сразу отпали сами собой. Сам языковой документ был десятки раз перепроверен. Все StaticText'ы из вышеуказанного кода практически идентичны за исключением разве что имён, положения на форме да надписей на них.

ВОПРОС: Что это может быть и как с этим бороться?

З.Ы. Версия Delphi 7.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.08.2010, 03:02
Ответы с готовыми решениями:

Ошибка при работе с XML
Нужно данные с XML файла переместить в коллекцию. Вот сам XML файл &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;User...

Ошибка при работе Delphi 7
Сейчас на моем раб.столе около 30 таких окошек. Мне ну очень надоела эта ошибка! Это жуть неудобно. Можно избавиться как то? :cry:

Ошибка Invalid argument supplied for foreach при работе с XML
Добрый день. Написал обработчик xml-файла, появляется ошибка Invalid argument supplied for foreach() in... Файл следующий: ...

10
Почетный модератор
 Аватар для Puporev
64315 / 47611 / 32743
Регистрация: 18.05.2008
Сообщений: 115,167
30.08.2010, 06:46
Просто интуитивно, судя по названиям параметров логичнее сначала open, а потом save...
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
30.08.2010, 12:15  [ТС]
Цитата Сообщение от Puporev Посмотреть сообщение
логичнее сначала open, а потом save
Вот и программа, видимо, так же считает
Только вот на самом деле в теле функции xlng_translate_statictext, кроме поиска ноды в языковом документе и изменения заголовка и подсказки StaticText'а согласно значениям ноды ничего не происходит. Никаких операций с файлами. К слову сказать, Save может стоять до Open. Главное, чтобы open в конце не было.
0
{c0Der}
 Аватар для Markus_13
138 / 123 / 18
Регистрация: 20.02.2009
Сообщений: 434
Записей в блоге: 4
30.08.2010, 16:54
Цитата Сообщение от Puporev Посмотреть сообщение
Просто интуитивно, судя по названиям параметров логичнее сначала open, а потом save...
Хых, а какая разница если это просто названия компонентов?))

Цитата Сообщение от Xander_Bass
ВОПРОС: Что это может быть и как с этим бороться?
Немогу точно сказать что это, т.к. кода я не видел, но могу посоветовать: брось эти буржуйские заморочки (это я про XML =) и работай с ini-файлом или txt'шкой...



Таак.. ладно, у меня сегодня настроение хорошее - поделюсь с вами своей процедуркой смены языка для форм:
(думаю будет полезно всем, кто интересуется вопросом "как создать мультиязыковое приложение")
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const div1='«'; div2='»'; div3='¦';
type twocharz=string[2];myint=-1..65533;
var msgs:array[0..1]of string[$FF];msgl:twocharz;
procedure changeLng(Lng:twocharz;Form:tForm;LngFile:string='lng.dat');
var s,h,n:string;l:tStringList;i,k,v:myint;c:tComponent;
begin
l:=tStringList.Create;
l.LoadFromFile(LngFile);
if Form<>nil then begin
i:=l.IndexOf(div1+Form.Name+div2+Lng);
if i>-1 then begin
for k:=i+1 to l.Count-1 do begin
s:=l.Strings[k];
if s[1]=div1 then break;
v:=pos('=',s);
if v=0 then continue;
if v=1 then begin
Form.Caption:=copy(s,2,length(s)-1);
end;
n:=copy(s,1,v-1);
s:=copy(s,v+1,length(s)-v);
v:=pos(div3,s);
if v>1 then begin
h:=copy(s,v+1,length(s)-v);
s:=copy(s,1,v-1);
end else h:='';
c:=Form.FindComponent(n);
if c=nil then continue;
try
if h<>'' then begin
tLabel(c).Hint:=h;
tLabel(c).ShowHint:=true;
end;
if s<>'' then tLabel(c).Caption:=s;
except end;
end;
Form.Update;
end;
changeLng(Lng,nil,LngFile);
end else begin
if msgl<>Lng then begin
i:=l.IndexOf(div1+div2+Lng);
if i>-1 then begin
for k:=i+1 to l.Count-1 do begin
s:=l.Strings[k];
if s[1]=div1 then break;
v:=pos('=',s);
if v=0 then continue;
n:=copy(s,1,v-1);
s:=copy(s,v+1,length(s)-v);
try v:=strtoint(n);
except continue;end;
if(v>=low(msgs))and(v<=high(msgs))then msgs[v]:=s;
end;
end;
msgl:=Lng;
end;
end;
l.Free;
end;
Процедура меняет капшоны и хинты для всех компонентов, для которых найдет данные в файле.
Входные параметры: "код языка"; форма; имя языкового файла.
По поводу констант: div1 - открывающая кавычка; div2 - закрывающая кавычка; div3 - разделитель заголовка и подсказки.
По поводу глоб.переменных: msgs - массив строк сообщений; msgl - текущий язык сообщений (чтобы лишний раз не перезагружать, т.к. смена языка сообщений вызывается для каждой формы, а предполагается что этот массив един для всего приложения).
Чтобы "искусственно" сменить язык сообщений (не меняя язык форм) вызовите процедуру с параметром nil вместо формы.

Вот пример языкового файла:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
«form1»RU
=Форма
b_change=Сменить язык
b_date=Сегодняшняя дата
label1=Заголовок1¦Подсказка1
button1=Заголовок2¦Подсказка2
checkbox1=Заголовок3
panel1=Заголовок4
«form1»EN
=Form
b_change=Change language
b_date=Today's date
label1=Caption1¦Hint1
button1=Caption2¦Hint2
checkbox1=Caption3
panel1=Caption4
«»RU
0=Вы действительно хотите выйти?
1=Сегодня:
«»EN
0=Are u really want 2 quit?
1=Today:
Если кто не понял как это юзать - качайте приложение, иллюстрирующее практическое применение приведенной процедуры:
Вложения
Тип файла: zip MultiLngExmpl.zip (158.7 Кб, 28 просмотров)
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
30.08.2010, 18:46  [ТС]
Цитата Сообщение от Markus_13 Посмотреть сообщение
брось эти буржуйские заморочки (это я про XML =) и работай с ini-файлом или txt'шкой...
И рад бы, но эта технология предназначена не только для "настольных" приложений, но и для веб-приложений (для CMS, например)
0
{c0Der}
 Аватар для Markus_13
138 / 123 / 18
Регистрация: 20.02.2009
Сообщений: 434
Записей в блоге: 4
30.08.2010, 18:51
Я уже написал:
Цитата Сообщение от Markus_13
Немогу точно сказать что это, т.к. кода я не видел
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
30.08.2010, 19:19  [ТС]
Markus_13, код чего именно тебе нужно увидеть? Если процедуры, то вот:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
function xlng_find_language_node(LangDoc: TXMLDocument; Language: ShortString): IXMLNode; stdcall; 
{ Поиск языковой ноды }
var
  c: integer;
  ln: IXMLNode;
begin
  c:=0;
  while c <> LangDoc.DocumentElement.ChildNodes.Count do
{ Сравнение содержимого атрибута id ноды с искомым идентификатором }
  if VarToStr(LangDoc.DocumentElement.ChildNodes[c].Attributes['id']) = Language then
  begin { Нода найдена }
    ln:=LangDoc.DocumentElement.ChildNodes[c];
    c:=LangDoc.DocumentElement.ChildNodes.Count
  end else
  begin
    c:=c+1; { Нода не найдена }
  end;
  result:=ln
end;
 
function xlng_find_xmlnode_by_name(LangDoc: TXMLDocument; ComponentName: ShortString; Language: ShortString): IXMLNode; stdcall; // Поиск ноды по имени компонента
var
  c: integer;
  res, ln: IXMLNode;
begin
  res:=NIL;
  if LangDoc.Active then
  begin
    ln:=xlng_find_language_node(LangDoc, Language); // Поиск языка. Выше
    if ln <> NIL then
    begin
      c:=0;
      while c <> ln.ChildNodes.Count do
{ Сравниваем содержание атрибута name ноды с искомым именем }
      if VarToStr(ln.ChildNodes[c].Attributes['name']) = ComponentName then 
      begin { Имя найдено }
        res:=ln.ChildNodes[c];
        c:=ln.ChildNodes.Count
      end else c:=c+1 { Имя не найдено }
    end
  end;
  result:=res
end;
 
function xlng_component_caption(LangDoc: TXMLDocument; ComponentName: ShortString; Language: ShortString): ShortString; stdcall; // Поиск кэпшна
var
  xn: IXMLNode;
  rbf: ShortString;
  res: ShortString;
begin
  res:='';
  xn :=xlng_find_xmlnode_by_name(LangDoc, ComponentName, Language); // Поиск ноды. Выше
  if xn <> NIL then
  begin
    rbf:=xn.Text; // Ищем в текстовом содержании ноды
    if Length(rbf) <= 254 then
    if rbf = '' then res:='-em-' else res:=rbf // Нода пустая
    else res:='-tl-' {res:=Copy(rbf,1,255)} // Нода слишком большая
  end else res:='-nn-'; // Нода не найдена
  result:=res
end;
 
function xlng_component_hint(LangDoc: TXMLDocument; ComponentName: ShortString; Language: ShortString): ShortString; stdcall; // Поиск подсказки
var
  xn: IXMLNode;
  rbf: ShortString;
  res: ShortString;
begin
  res:='';
  xn :=xlng_find_xmlnode_by_name(LangDoc, ComponentName, Language);
  if xn <> NIL then
  begin
    rbf:=VarToStr(xn.Attributes['hint']); // Ищем в атрибуте HINT
    if Length(rbf) <= 254 then
    if rbf = '' then res:='-eh-' else res:=rbf
    else res:='-lh-' {res:=Copy(rbf,1,255)}
  end else res:='-nh-';
  result:=res
end;
 
function xlng_translate_statictext(LangDoc: TXMLDocument; Component: TStaticText; Language: ShortString): byte; stdcall; // Функция, вызывающая исключение
var
  res: byte;
  sb: ShortString;
begin
  sb:=xlng_component_caption(LangDoc, Component.Name, Language); // Ищем ноду с кэпшном. Выше
  res:=0;
  if sb = '-em-' then res:=$21; // Пустая строка
  if sb = '-tl-' then res:=$22; // Строка большая, чем 254 символа
  if sb = '-nn-' then res:=$20; // Нода не найдена
  if res = 0 then Component.Caption:=sb;
  if res = 0 then
  begin
    sb:=xlng_component_hint(LangDoc, Component.Name, Language); // То же самое, только с подсказкой
    if sb = '-eh-' then res:=$25;
    if sb = '-lh-' then res:=$26;
    if sb = '-nh-' then res:=$24;
    if res = 0 then Component.Hint:=sb
  end;
  result:=res
end;
Полный текст обработчика, где используются процедуры:

Delphi
1
2
3
4
5
6
7
8
9
10
11
procedure TXLNGEditor.TranslateForm;
begin
  xlng_translate_statictext(XMLDocument,stt_key,'RU');
  xlng_translate_statictext(XMLDocument,stt_value,'RU');
  xlng_translate_statictext(XMLDocument,stt_save,'RU');
  xlng_translate_statictext(XMLDocument,stt_open,'RU');
  SaveDialog.Title:=stt_save.Caption;
  OpenDialog.Title:=stt_open.Caption;
  VLEdit.TitleCaptions.Strings[0]:=stt_key.Caption;
  VLEdit.TitleCaptions.Strings[1]:=stt_value.Caption;
end;
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
31.08.2010, 15:26  [ТС]
Исключение выплывает в самом конце, после Application.Run. Притом сообщение выглядит так:

Project ... raised too many consecutive exceptions: 'access violation at 0x00543532 : read of adress 0x00b91064
.

При выполнении приложения исключений не возникает.
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
01.09.2010, 13:58  [ТС]
А вот теперь самое интересное. Каким-то чудом исключение на статиктекстах самоликвидировалось. Исключение вызывается только процедурами обработки меню. Больше никакими. Грубо говоря если мы обрабатываем объект типа TMenuItem или TMainMenu то это порождает RunError при завершении приложения. В остальных случаях этого не происходит.
0
{c0Der}
 Аватар для Markus_13
138 / 123 / 18
Регистрация: 20.02.2009
Сообщений: 434
Записей в блоге: 4
01.09.2010, 16:50
А вот теперь самое интересное. Каким-то чудом исключение на статиктекстах самоликвидировалось. Исключение вызывается только процедурами обработки меню. Больше никакими. Грубо говоря если мы обрабатываем объект типа TMenuItem или TMainMenu то это порождает RunError при завершении приложения. В остальных случаях этого не происходит.
"самоликвидировалось" - такого быть не может, только если кто-то через бэкдор в твоих кодах покопался и исправил что-то

"Исключение вызывается только процедурами обработки меню. Больше никакими." - и что? на какую ты помощь рассчитываешь по такой скудной информации?
Если исключение вызывается - удали эти процедуры =), больше я тебе ничего посоветовать не могу...
0
Йошь-мыслитель
 Аватар для Xander Bass
126 / 120 / 26
Регистрация: 22.02.2009
Сообщений: 706
Записей в блоге: 5
02.09.2010, 20:10  [ТС]
Цитата Сообщение от Markus_13 Посмотреть сообщение
на какую ты помощь рассчитываешь по такой скудной информации?
Может я что-то упустил из виду при программировании этих процедур (исходный код выше)?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.09.2010, 20:10
Помогаю со студенческими работами здесь

Постоянно вылетает ошибка при работе с INI файлами в Delphi 7
Не могу работать с INI файлами , постоянно вылетают ошибки , никаких синтаксических ошибок в коде нету. Вот простой пример программы ,...

Баг при работе с xml Document: ошибка RuntimeException "Event notification set size exceeded
Была поставлена простенькая задача. Чтобы в одном большом проекте была возможность редактировать некие xml файлики. Я в начале это сделал...

Аппаратная ошибка видео (Ошибка при работе с видеоустройствами привела к некорректной работе Windows).
Аппаратная ошибка видео. Последнее время во время игры Call of Duty: Modern Warfare 2 в мультиплеер, (между сменами карт, как только...

TZipFile в Delphi. Ошибка при работе с архивами "Архив поврежден"
Добрый день! Использование RAR из под delphi xe5 Интересует тема по работе с zip, rar файлами из под delphi. Ранее использовал родной...

Ошибка в Delphi при работе с БД "DBEdit Field 'Название столбца' not found"
Помогите пожалуйста не знаю как описать проблему, но напишу. Решить я создал кнопку &quot;Открыть&quot; ну с помощью её я открываю БД у...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru