Форум » [x]Harbour » Снова XML » Ответить

Снова XML

Dima: Нужно создавать / читать XML в UTF-16 Что есть в этом плане в Harbour ? Минимум нужно корректное чтение !

Ответов - 61, стр: 1 2 3 4 All

Dima: Pasha пишет: Как вариант: перекодировать файл в utf-8, работать с ним Павел наверное знает как , но пока молчит.

Pasha: Перекодировать можно вызовом: Extern HB_CODEPAGE_UTF8, HB_CODEPAGE_UTF8EX, HB_CODEPAGE_UTF16LE .. c2 := HB_Translate(c1, 'UTF8', 'UTF16LE') ну и наоборот. И маленькая хитрость: вместо того, чтобы создавать промежуточные файлы, можно для класса HXMLDoc вместо метода read использовать метод ReadString: oXml:ReadString(HB_Translate(memoread(cFileName), 'UTF16LE', 'UTF8'))

Dima: Да Паш это работает , спасибо !


Dima: Из доки по мобильной проге [pre2] "3935BEAE-9F40-4BA5-BA9E-03F860CC1750" "3343E400-1577-4DDE-9A82-BF1E53267FD6" Идентификатор GUID имеет строго определенную структуру. Он состоит из 5 групп символов. Первая группа состоит из 8 символов, вторая – из 4 символов, третья – из 4 символов, четвертая – из 4 символов, пятая группа – из 12 символов. Не допускаются пробелы перед идентификатором и после идентификатора, указание разделителей "-" между символами в приведенных выше позициях обязательно. Фигурные скобки перед и после идентификатора недопустимы (принятое обозначение для идентификаторов в OLE). Допустимые символы в идентификаторе: от "0" до "9" и от "A" до "F" (или от "a" до "f"). [/pre2] А теперь вопрос. В моей программе в справочнике контрагентов коды организаций представлены в виде поля "kod_kl" "n" , 6 ,0. Все коды уникальны. Мобильная база ни чего про мои коды не знает а понимает только GUID. Есть ли функция преобразующая число в GUID и наоборот (из GUID получить мой обычный код) ?

PSP: Dima пишет: Есть ли функция преобразующая число в GUID и наоборот (из GUID получить мой обычный код) ? ЧислА длиной 6 знаков явно мало для отражения кода GUID. Может лучше в строку? Цифры из GUID от "0" до "9" преобразуются в "00" - "09", а цифры от "А" до "F" в "10" - "15". Обратно также. Т.е., на каждый символ GUID - 2 символа твоей строки. Дефисы оставить для удобства. Длина постоянна. Вариант 2: создать у себя поле GUID для соответствия kod_kl. update: точнее, имхо, вариант один: создать у себя поле GUID, чтобы получить однозначное соответствие с kod_kl

Pasha: Для хранения guid в числовом формате необходимо 16 байт, или 128 бит. Это 2 64-битных целых, учитывая нынешнюю архитектуру. Или две числовых переменных харбора. А его строковое представление - это просто запись в 16-ричном формате, с разбивкой на группы. Соответственно, преобразующая функция - это любая функция для преобразований 16-ричных значений. Но вопрос: стоит ли делать такие преобразования ? Может лучше привязать kod_kl к guid в его строковом представлении, как предложил PSP ?

Dima: То есть пойти тупо в лоб мануальным путем ? Есть у меня код клиента 123 Преобразую его так скажем в GUID , вида GUID="00000123-0001-0000-0000-000000000000" Где в первой части код клиента , во второй признак 1 что это контрагент Группы товара GUID="00000007-0002-0000-0000-000000000000" Где в первой части код группы , во второй признак 2 что это группа товара Товарная позиция GUID="00000301-0003-0000-0000-000000000000" Где в первой части код товара , во второй признак 3 что это товарная позиция C ихними GUID точно не пересечется. Как они посчитали GUID ниже х... знает [pre2] <ELEMENTS> <ITEM GUID="BD72D900-55BC-11D9-848A-00112F43529A" IsDeleted="0" Name="Торговый дом &quot;Комплексный&quot; " A02="0" A05="7705260699" A06="770501001" A07="" A04="(095) 1123456, доб. 789" A03="117452, Москва г, Симферопольский б-р, дом № 78, корпус 1" A09="112435, Москва, Одесская улица, дом № 67, корпус 1, кв.78" A010="ТД"/> <ITEM GUID="EF8F948C-8403-11DA-9AE9-000D884F5D77" IsDeleted="0" Name="Cтройснаб" A02="1" A05="7723240668" A06="772301001" A07="" A04="" A03="" A09="" A010="ССН"/> </ELEMENTS> [/pre2] Завтра задам вопрос разрабам.

Pasha: Дык A05 - это ИНН, A06 - КПП, что однозначно определяет контрагента

Dima: Pasha пишет: Дык A05 - это ИНН, A06 - КПП, что однозначно определяет контрагента Эти реквизиты заполнены не у всех :)

Dima: SergKis В общем сделал так в тестовом варианте , вроде пашет. [pre2] cc:=hb_MemoRead(hb_DirBase()+"tocdb.xml") oXml := HXMLDoc():ReadString( cc ) if oXml==nil return nil endif o:=oXml:find("DATAEXPORT") if o==nil return nil endif o1:=o:find("DOCUMENTS") if o1==nil return nil endif for i=1 to len(o1:aitems) j := o1:aItems[ i ] if j==nil return nil endif if j:title=="DOCUMENT" .and. j:GetAttribute("GUID")=="E01E1F5C-D6E4-46E8-B923-3758B0D79BDE" o2:=j:find("ELEMENTS") if o2==nil return nil endif for k=1 to len(o2:aitems) t:=o2:aItems[ k ] if t==nil return nil endif ? t:GetAttribute("GUID"),t:GetAttribute("DT"),t:GetAttribute("DocNumber") // читаем заголовок заявки t1:=t:find("TABLES") if t1==nil return nil endif t2:=t1:find("TABLE") if t2==nil return nil endif for z=1 to len(t2:aitems) // читаем содержимое заявки ee:=t2:aItems[ z ] ? ee:title,ee:GetAttribute("A05"),ee:GetAttribute("DocID") next next exit endif next [/pre2] Сам XML <?xml version="1.0" encoding="UTF-8"?> <DATAEXPORT mt="1.95"> <DOCUMENTS> <DOCUMENT GUID="E01E1F5C-D6E4-46E8-B923-3758B0D79BDE" Comment="Заказы" KILLALL="1"> <ELEMENTS> <ITEM GUID="00000001-0000-0000-0000-00005790AFF7" DT="2016-07-21T14:20:23" IsDeleted="0" IsPost="1" DocNumber="ORD0090B01A" A02="AAAAAAAA-8403-11DA-9AE9-000D884F5D77" A03="00001366-5E19-55CC-1000-15A4567E8788" A04="" A05="" A06="0" A07="" A071="666F1FA8-B78B-0003-9200-88CE8BCECF2B" A090="C1F49005-FCBD-449B-99A0-1B6C63992240" A08="43.5" A010="2016-07-23T14:20:23" A011="" A012="" A016="0" GUID_BACKPRODUCT="00000007-0000-0000-0000-00005790AFF7" A091="" > <TABLES> <TABLE GUID="0738E61B-F06F-464A-8483-4249E0254819"> <ITEM GUID="00000002-0000-0000-0000-00005790B07D" DocID="00000001-0000-0000-0000-00005790AFF7" A01="00002172-A789-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="1" A05="24.5" A06="24.5" A015="null" /> </TABLE> </TABLES> </ITEM> <ITEM GUID="00000001-0000-0000-0000-0000578CD6F0" DT="2016-07-18T16:17:36" IsDeleted="0" IsPost="1" DocNumber="ORD008CD703" A02="AAAAAAAA-8403-11DA-9AE9-000D884F5D77" A03="00001384-55BC-11D9-848A-00112F43529A" A04="" A05="" A06="0" A07="" A071="666F1FA8-B78B-0003-9200-88CE8BCECF2B" A090="C1F49005-FCBD-449B-99A0-1B6C63992240" A08="2343.7" A010="2016-07-20T16:17:36" A011="" A012="" A016="0" GUID_BACKPRODUCT="00000007-0000-0000-0000-0000578CD6F0" A091="" > <TABLES> <TABLE GUID="0738E61B-F06F-464A-8483-4249E0254819"> <ITEM GUID="00000002-0000-0000-0000-00005790AB6C" DocID="00000001-0000-0000-0000-0000578CD6F0" A01="00002172-A789-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="77" A05="24.5" A06="1886.5" A015="null" /> <ITEM GUID="00000002-0000-0000-0000-00005790ABC7" DocID="00000001-0000-0000-0000-0000578CD6F0" A01="00001C62-A789-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="12" A05="38.1" A06="457.2" A015="null" /> </TABLE> </TABLES> </ITEM> <ITEM GUID="00000001-0000-0000-0000-00005791B4F0" DT="2016-07-22T08:53:52" IsDeleted="0" IsPost="1" DocNumber="ORD0091B54D" A02="AAAAAAAA-8403-11DA-9AE9-000D884F5D77" A03="000012C1-5E19-55CC-1000-15A4567E8788" A04="" A05="" A06="0" A07="" A071="666F1FA8-B78B-0003-9200-88CE8BCECF2B" A090="C1F49005-FCBD-449B-99A0-1B6C63992240" A08="1269" A010="2016-07-24T08:53:52" A011="" A012="" A016="0" GUID_BACKPRODUCT="00000007-0000-0000-0000-00005791B4F0" A091="" > <TABLES> <TABLE GUID="0738E61B-F06F-464A-8483-4249E0254819"> <ITEM GUID="00000002-0000-0000-0000-00005791B508" DocID="00000001-0000-0000-0000-00005791B4F0" A01="000002A1-0002-34AC-1989-823456778888" A02="" A03="00000001-ABCD-CCCC-7777-888888888888" A04="3" A05="8.6" A06="25.8" A015="null" /> <ITEM GUID="00000002-0000-0000-0000-00005791B528" DocID="00000001-0000-0000-0000-00005791B4F0" A01="00000493-0002-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="14" A05="88.8" A06="1243.2" A015="null" /> </TABLE> </TABLES> </ITEM> <ITEM GUID="00000001-0000-0000-0000-00005791B55B" DT="2016-07-22T08:55:39" IsDeleted="0" IsPost="1" DocNumber="ORD0091B58F" A02="AAAAAAAA-8403-11DA-9AE9-000D884F5D77" A03="000013B8-5E19-55CC-1000-15A4567E8788" A04="" A05="" A06="0" A07="" A071="666F1FA8-B78B-0003-9200-88CE8BCECF2B" A090="C1F49005-FCBD-449B-99A0-1B6C63992240" A08="13291.2" A010="2016-07-24T08:55:39" A011="" A012="" A016="0" GUID_BACKPRODUCT="00000007-0000-0000-0000-00005791B55B" A091="" > <TABLES> <TABLE GUID="0738E61B-F06F-464A-8483-4249E0254819"> <ITEM GUID="00000002-0000-0000-0000-00005791B56D" DocID="00000001-0000-0000-0000-00005791B55B" A01="0004F50B-0002-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="85" A05="62" A06="5270" A015="null" /> <ITEM GUID="00000002-0000-0000-0000-00005791B579" DocID="00000001-0000-0000-0000-00005791B55B" A01="00000FF1-0002-34AC-1989-823456778888" A02="" A03="00000002-ABCD-CCCC-7777-888888888888" A04="89" A05="84.1" A06="7484.9" A015="null" /> <ITEM GUID="00000002-0000-0000-0000-00005791B583" DocID="00000001-0000-0000-0000-00005791B55B" A01="000012C8-0001-34AC-1989-823456778888" A02="" A03="00000001-ABCD-CCCC-7777-888888888888" A04="31" A05="17.3" A06="536.3" A015="null" /> </TABLE> </TABLES> </ITEM></ELEMENTS> </DOCUMENT> <DOCUMENT GUID="61DEE5FE-D0A8-4842-A6AF-A8D33F298845" Comment="Мерчендайзинг" KILLALL="1"> <ELEMENTS></ELEMENTS> </DOCUMENT> <DOCUMENT GUID="E59B1899-60C8-497E-99B1-6A04DEC063FA" Comment="Касса" KILLALL="1"> <ELEMENTS></ELEMENTS> </DOCUMENT> <DOCUMENT GUID="B49074D6-3C0C-4361-B71D-BBF446AB02B6" Comment="Задания" KILLALL="1"> <ELEMENTS></ELEMENTS> </DOCUMENT> <DOCUMENT GUID="4971B041-BEAB-4FA6-B1E8-10138F04FE44" Comment="Возврат товаров" KILLALL="1"> <ELEMENTS></ELEMENTS> </DOCUMENT> </DOCUMENTS> </DATAEXPORT>

SergKis: Dima Предлагаю подумать над таким решением (схема) [pre] aHDokum := hb_Hash() // список обраб. документов xml hb_HSet(aHDokum, "E01E1F5C-D6E4-46E8-B923-3758B0D79BDE", {|o,n| Zajavka1( o, n ) }) hb_HSet(aHDokum, "E01E1F5C-D6E4-46E8-B923-3758B0000ABC", {|o,n| Zajavka2( o, n ) }) ... // в коде ... // вместо // if j:title=="DOCUMENT" .and. j:GetAttribute("GUID")=="E01E1F5C-D6E4-46E8-B923-3758B0D79BDE" // делаем if j:title=="DOCUMENT" b := hb_HGetDef(aHDokum, j:GetAttribute("GUID"), Nil) If b != Nil Eval(b, j, i) EndIf ... Function Zajvka1( oXml, nElm ) Local b, i, k, s, v, oe, ot, ots, ote Local aStru := {...} // структура врем.файла куда съедать данные Local aHAtr := hb_Hash() hb_HSet(aHAtr, "GUID" , {|o,i,p,v| FieldPut(FieldPos(p), v) }) hb_HSet(aHAtr, "DT" , {|o,i,p,v| FieldPut(FieldPos(p), v) }) hb_HSet(aHAtr, "DocNumber", {|o,i,p,v| FieldPut(FieldPos(p), v) }) hb_HSet(aHAtr, "A05" , {|o,i,p,v| FieldPut(FieldPos(p), v) }) hb_HSet(aHAtr, "DocID" , {|o,i,p,v| FieldPut(FieldPos(p), v) }) oe := oXml:find("ELEMENTS") if oe == nil ? "Error xml structure" return .F. endif for k=1 to len(oe:aitems) ot:=o2:aItems[ k ] if ot==nil return .F. endif For i := 1 To len(ot:aAttr) s := ot:aAttr[ i ][1] b := hb_HGetDef(aHAtr, s, Nil) If b != Nil v := ot:aAttr[ i ][2] Eval( b, ot, i, s, v ) EndIf Next // ? t:GetAttribute("GUID"),t:GetAttribute("DT"),t:GetAttribute("DocNumber") // читаем заголовок заявки ots:=ot:find("TABLES") if ots==nil return .F. endif ote:=ots:find("TABLE") if ote==nil return .F. endif For i := 1 To len(ote:aAttr) s := ote:aAttr[ i ][1] b := hb_HGetDef(aHAtr, s, Nil) If b != Nil v := ote:aAttr[ i ][2] Eval( b, ote, i, s, v ) EndIf Next ... Return .T. Function Zajvka2( o ) ... Return .T. [/pre]

Dima: SergKis Спасибо , изучу подход

Dima: Есть вот такой XML , таблица в общем [pre2] <?xml version="1.0" encoding="utf-8"?> <points> <tt> <id>526645</id> <code1C>12345</code1C> <name>Зиневич проба</name> <client>Зиневич</client> <address></address> <lon>0</lon> <lat>0</lat> <radius>100</radius> <comment></comment> <user></user> <enabled>true</enabled> </tt> <tt> <id>526750</id> <code1C>359514069607817_new_01-03-04</code1C> <name>чп Тригуба</name> <client>Завгородний</client> <address>Таврийск, вулиця Зои Комсмедемянской 15</address> <lon>33.4453</lon> <lat>46.7576</lat> <radius>100</radius> <comment>работаем</comment> <user></user> <enabled>false</enabled> </tt> </points> [/pre2] Попытался ее прочитать с помощью библитеки Кресина. [pre2] oXml := HXMLDoc():ReadString( hb_MemoRead("1.xml") ) if oXml==nil return nil endif o:=oXml:find("points") if o==nil return endif FOR i=1 to len(o:aitems) o1 := o:aItems[ i ] // полагал что тут будет работать o1:GetAttribute("id") или o1:GetAttribute("code1C") но выдает NIL // поэтому слепил код что ниже //? hb_valtoexp(o1) if o1:Title=="tt" for j=1 to len(o1:aitems) o2:=o1:aItems[ j ] ? o2:Title,if( len(o2:Aitems)#0,o2:Aitems[1],"") next endif wait NExt [/pre2] Вопрос в коменте кода. Не так его разбираю что ли ?

SergKis: Dima Атрибут это внутри тега <tag1 attr1 = "aaa" attr2 = "bbb">value</tag1> получив oXml сделай for i := 1 to len(oXml:aItems) ? valtype(oXml:aItems[ i ]), oXml:aItems[ i ] next и см. что там

SergKis: PS если обект, то ? oXml:aItems[ i ]:Title

Dima: Сергей Tiltle я считал , показал как в коде выше А как считать значение ? Получается только так [pre2] if o1:Title=="tt" for j=1 to len(o1:aitems) o2:=o1:aItems[ j ] ? o2:Title,if( !empty(o2:Aitems),o2:Aitems[ 1] ,"--------") next endif [/pre2] В общем ладно , работает да и бог с ним. Спасибо ! На выходе по этому коду что выше получаю так [pre2] id 526645 code1C 12345 name Зиневич проба client Зиневич address -------- lon 0 lat 0 radius 100 comment -------- user -------- enabled true [/pre2]

SergKis: Dima Если бы прокрутил цикл, увидел, как все устроено, т.е. o:title == "points" будет содержать объект, в котором o:find('tt') вернет обект, в котором o:find('id') вернет значение id тега, т.е. извлекаем данные o:find('code1C') и т.д.

Dima: SergKis Попробовал , не получилось. Оставил так [pre2] o:=oXml:find("points") if o==nil return endif FOR i=1 to len(o:aitems) o1 := o:aItems[ i ] if o1:Title=="tt" for j=1 to len(o1:aitems) o2:=o1:aItems[ j ] ? o2:Title,if( !empty(o2:Aitems),o2:Aitems[ 1 ],"--------") next endif NEXT [/pre2]

SergKis: Dima пишет Попробовал , не получилось. Глянул у себя, почему работает ? Нашел - правил метод Find[pre2] METHOD Find( cTitle,nStart,block ) CLASS HXMLNode Local i IF nStart == Nil nStart := 1 ENDIF If len(::aItems) == 1 .and. Valtype(::aItems[1]) == "C" Return ::aItems[1] EndIf DO WHILE .T. i := Ascan( ::aItems,{|a|Valtype(a)!="C".AND.a:title==cTitle},nStart ) IF i == 0 EXIT ELSE nStart := i IF block == Nil .OR. Eval( block,::aItems ) Return ::aItems ELSE nStart ++ ENDIF ENDIF ENDDO Return Nil [/pre2]

Dima: Понял Сергей. Не люблю я править авторские сырцы. Спасибо за желание помочь !



полная версия страницы