XML C8 - не понял...

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Вот примеры выше и раскодируют UTF-8 в ASCII
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8081
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 29 раз
Поблагодарили: 98 раз

XML C8 - не понял...

Сообщение Игорь Столяров »

Yufil писал(а): Одно маленькое НО - возвращаются строки в UTF-8, их надо раскодировать
Это понятно. После раскодирования вместо русского текста в C63 какой-то мусор.
Я ведь написал, тот же самый код собранный в C91 - прекрасно загружает русский текст. ;)
Здесь правда, надо добавить что речь идет о загрузке XML в очередь методом FromXMLFile() с последующим распарсиванием.
Make Clarion Great Again ! 😎
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Дык, у меня куча приложений с XML. По крайней мере, в CW6 парсер при декодировании UTF-8 выдаёт и значения в UTF-8
А дальше - обращение к классу CSTR для перекодировки из UTF-8 в Windows-1251

Кстати, тот же класс поможет и создать XML

Код: Выделить всё

SaveManifest    ROUTINE  ! Сохранить манифест
                DATA
CS              CSTR                
                CODE
                CS.Set('<<?xml version="1.0" encoding="UTF-8" ?>')
                CS.CAT('<13,10><<structure>')                
                CS.Cat('<13,10><<program title="' & ANSI2HTML(Loc:MName) & '"/>')
                LOOP ManQ# = 1 to Records(ManQ) 
                  Get(ManQ, ManQ#) 
                  CS.Cat('<13,10><<topic level="' & ManQ:Level |
                  & '" id="' & Clip(ManQ:ID) & '" name="' & ANSI2HTML(ManQ:Name) & '" />') 
                END   
                CS.Cat('<13,10><</structure>') 
                CS.ToUTF8() 
                CS.SaveToFile(Loc:ManifestFileName) 
                EXIT 
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

Не удается прикрутить код, Юрий! В глобальных вставках пишу Include('...'), в процедуре обьявляю переменную типа CStr. Приложение - multiDLL + EXE.
При первом же вызове процедуры из основного фрейма - AV...
Убираю декларацию переменной - процедура работает. А толку? В чем затык? Так сказать, в чем нюанс?..
-------------------------------
В истинном золоте блеска нет...
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Я помещаю Include ('cstr.inc') в глобальную секцию данных, потом добавляю драйвер DOS, если нужно. И всё работает.
Куча приложений от CW5 до СW9 функционируют

Скорее всего, XML не в UTF-8.

Пришли, плиз, свой XML на yufil@mail.ru или на padreyufil@gmail.com, посмотрю
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

да, все так и сделано. и драйвер ДОС добавлен. Но дело не доходит вообще до работы с файлами - процедура тупо валится на этапе инициализации, если обьявлена переменная типа cstr - то есть валится даже не на первом операторе, а где-то раньше...
-------------------------------
В истинном золоте блеска нет...
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Если падает при объявлении, значит глючит конструктор, поставьте дебаг туда. Но там всё настолько очевидно...

Self.S &= New CString(2)
Self.S = ''
Self.Len=0

Или попробуйте вместо

CS Cstr

написать CS Class(Cstr)
END

Или даже
СS &Cstr

CS &= New Cstr
....
Dispose(CS)

Правда, с CW8 не работал, как-то он у меня не пошёл...
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

7 Май 2015, 7:02
Если падает при объявлении, значит глючит конструктор, поставьте дебаг туда. Но там всё настолько очевидно...
С этого и начал. Не доходит даже до первого оператора...
Или даже
СS &Cstr
Это было второй попыткой. Компилиться не захотел...
написать CS Class(Cstr)
END
Вот это попробую. Хотя как-то мудрено... Тот же ХМЛ класс при обьявлении переменных ведет себя нормально...
-------------------------------
В истинном золоте блеска нет...
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

УРА! Как ни странно, такое обьявление переменной пришлось кларе по душе! ASCII-XML файл считан!!! И даже по-русски выводит! Код следующий:

Код: Выделить всё

Doc &= XMLStringToDOM(CS.S)
If Doc &= null Then Message('Aaaa!!!')
End
FillDOMQueue(Doc, ListXML)
Loop I# = 1 To Records(ListXML)
Get(ListXML, I#)
CS.Set(ListXML.node.GetNodeValue())
CS.ToASCII()
Stop(ListXML.level & ' - ' & ListXML.node.GetNodeName() & ' - ' & CS.S & ' - ' & ListXML.node.GetNodeType())
End
If not Doc &= null Then Doc.Dispose() End
 
Надеюсь память из-под CS высвобождать вручную не надо?
Ну теперь завтра займемся выковыриванием из ListXML атрибутов
:cat: Вроде судя по коду ViewXML это не особенно сложно.
Спасибо, Юрий! И всем, принимающим участие в дискуссии тоже спасибо!
-------------------------------
В истинном золоте блеска нет...
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Усердие всё превозмогает (К.Прутков) :)
А разборку строки с параметрами в этой ветке форума я уже давал, поищи чуть повыше...
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Кстати, не совсем правильный алгоритм.
Сначала надо запросить имя тэга через GetNodeName (кстати, он тоже в UTF-8, если допускаются русские теги, то и его надо перекодировать), а потом, в зависимости от NodeName, уже разбирать строку, пример выше.

Ну и Doс надо освободить в конце, командой
Doc.Release()

Кусок из реальной программы...
Некий файл (манифест) считывается в очередь ManQ

Код: Выделить всё

LoadManifest        ROUTINE  ! Загрузка манифеста 
                    DATA
xmlDoc              &Document,Auto
Nl                  &Nodelist,Auto
nnm                 &NamedNodeMap,auto
ANode               &Node,Auto
AttrIndex           Long
ListXML     queue(DOMQueue) ! Очередь для считывания параметров
            end
!               ! Создадим пустой манифест 
!               CS.Set('<<?xml version="1.0" encoding="UTF-8" ?>')
!               CS.CAT('<13,10><<structure>')                
!               CS.Cat('<13,10><<program title="Наименование проекта"/>')
!               CS.Cat('<13,10><<topic level=0 id="ГЛМЕНЮ" name="Главное меню" />') 
!               CS.Cat('<13,10><</structure>') 

                    CODE
                    Ret# = CS.LoadFromFile(Loc:ManifestFileName) 
                    If Ret#
                      Message('Ошибка загрузки манифеста ' & Loc:ManifestFileName )
                      Exit 
                    End
                    XmlDoc &= XmlStringToDom(CS.S)
                    If XMLDoc &= Null
                      Message('Ошибка разборки манифеста ' & Loc:ManifestFileName )
                      EXIT 
                    End
                    FillDomQueue(XMLDoc,ListXML,1)                    
                    FREE(ManQ) 
                    LOOP ListXML# = 1 to Records(ListXML) 
                       Get(ListXML, ListXML#) 
                       CASE lower(ListXML.Node.getNodeName())
                       OF 'topic'
                            nnm &= ListXML.Node.getAttributes()
                            IF not nnm &= null
                                Loop AttrIndex = 0 to nnm.getLength() - 1
                                    Anode &= nnm.item(AttrIndex)
                                    CS.Set(Anode.GetNodeValue())
                                    CS.ToAscii()
                                    Case lower(ANode.GetNodename())
                                    Of 'level' !               
                                        ManQ:Level = CS.S 
                                    OF 'id' 
                                        ManQ:ID = Clip(CS.S) 
                                    OF 'name' 
                                        ManQ:Name = Clip(CS.S)
                                    END 
                                END     
                                ADD(ManQ) 
                            END 
                       OF 'program' 
                            nnm &= ListXML.Node.getAttributes()
                            IF not nnm &= null
                                Loop AttrIndex = 0 to nnm.getLength() - 1
                                    Anode &= nnm.item(AttrIndex)
                                    CS.Set(Anode.GetNodeValue())
                                    CS.ToAscii()
                                    Case lower(ANode.GetNodename())
                                    Of 'title' !               
                                        Loc:MName=CS.S
                                    END 
                                END     
                            END ! If nnm &= Null 
                       END  ! Case NodeName 
                    END  ! Loop ListXML# 
                    XMLDoc.Release()
                    Display() 
                    EXIT 
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

Именно так (т.е. почти команда-в-команду!!!) и получилось :)
Не понял только, зачем Display() в конце. Вроде по коду никаких экранных переменных не наблюдается. А EXIT в конце роутины как дань порядку? :D
-------------------------------
В истинном золоте блеска нет...
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

Радостная эйфория четверга от продвинувшегося изучения XML и Cstr неожиданно сменилась пятничным разочарованием под стать московской погоде пятничного вечера. Оказалось, что всплыло море подводных камней следующего плана.
1. "Странное" обьявление переменной типа
CS Class(Cstr)
End
решило проблему РОВНО наполовину, ибо проблема теперь возникает в противоположном месте - процедура падает с AV при выходе из нее. Как я понимаю, при вызове деструктора. Однако, как и в случае с конструктором, дело не доходит даже до первого оператора метода. Подозреваю, что проблема все-таки в синтаксисе. На данный момент выкрутился, переименовав методы на Prepare() и UnPrepare() соответственно и вызывая их в начале и в конце процедуры. Не знаю, правильно ли это?
Теперь о наблюдениях...
2. Перенос обьявления переменной типа Cstr в секцию глобальных переменных, как ни странно, позволяет обьявить переменную нормальным способом:
CS Cstr
однако теперь AV будет вываливаться не в конце процедуры, а на выходе из программы. Видимо, т.к. схема ЕХЕ+мультиДЛЛ полагает статическую линковку дилелей, то и разынициализация происходит при завершении приложения в целом;
2. Если сменить обьявление класса с
cstr class,type,module('cstr.clw'),link('cstr.clw')
на
cstr class,type,module('cstr.clw'),link('cstr.clw',_cstrLinkMode_),dll(_cstrLinkMode_),
то 'нормальным' способом обьявить переменную удается даже в секции локальных данных. Правда, прм этом программа валится уже не на инициализации, а при первом обращении к этой переменной, т.е.
cs.loadfromfile(...)
Прошу помощи в разборе данной проблемы.......
Существует еще интересная штука, связанная с утечкой памяти при работе ХМЛ класса кларика, но об этом чуть позже - пора мыть ребенка :)))
-------------------------------
В истинном золоте блеска нет...
Аватара пользователя
Aragorn
Активист
Сообщения: 113
Зарегистрирован: 11 Июль 2005, 12:40
Откуда: Москва

XML C8 - не понял...

Сообщение Aragorn »

С памятью в ХМЛ по моим наблюдениям дело тоже швах.
1. В предложенном Yufil коде при многократной обработке файла большого обьема размер выделяемой памяти непрерывно растет. Можно сделать
nnm.release() в конце каждого цикла, где nnm &NamedNodeMap. Это устраняет прирост занимаемой памяти.
2. Однако!
Doc &= XMLStringToDom(CS.S)
Doc.Release()
не дает роста памяти, а вот если между операторами вставить
FillDOMQueue(...),
то отжирается приличный кусман памяти (в моем случае большого файла - около 40 кб), и не высвобождается до конца работы приложения. Правда, и прироста в дальнейшем повторном вызове не наблюдается...
В чем дело?... В очереди остаются обьекты?
-------------------------------
В истинном золоте блеска нет...
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

XML C8 - не понял...

Сообщение Yufil »

Ну, можно по концу очередь очистить, если есть желание. А новых объектов там быть вроде не должно. Насколько я понимаю, дерево разборки возвращает ссылки на разные места XML-текста, но не сами данные.
Что касается возврата памяти - а кто сказал, что память возвращается сразу? Обычно приложение имеет некий локальный пул памяти, а потом уже, при нехватке места, запрашивает дополнительную память у Windows. И 40К памяти на 18-мегабайтный файл - оно как-то не впечатляет.

А вот глюки с объектами Cstr очень странны, этот класс давно сделан и давно работает, правда, под CW5 и CW55 слегка урезается. Ну и пару
сомнительных мест уже лет пять как хочу поправить. Например, при конвертации в UTF-8 я считаю, что строка Unicode и UTF-8 в два раза длиннее исходной, а это не всегда так. Константу 1251 в тех же функциях заменить на вызов GetACP(), возвращающей текущую кодовую страницу.
Ответить