Форум » [x]Harbour » Проблема с именами тэгов на кирилице в XML файлах. Пособите пожалуйста » Ответить

Проблема с именами тэгов на кирилице в XML файлах. Пособите пожалуйста

AndreyZh: Наткнулся на "нежданчик". Оказывается раньше читал их XML файлов различных кодировок, где тэги были на латыни и всё было хорошо, например в файле всё будет замечательно работать [pre2] <?xml version="1.0" encoding="utf-8"?> <ORDER> <DOCUMENTNAME>220</DOCUMENTNAME> <NUMBER>23000B3094059</NUMBER> <DATE>2021-10-18</DATE> <DELIVERYDATE>2021-10-21</DELIVERYDATE> <DELIVERYTIME>00:00</DELIVERYTIME> </ORDER> [/pre2] Полностью работающая конструкция: oDoc := TXmlDocument():new() oDoc:read( MemoRead(cXml) ) oUrl := oDoc:findFirst( "DATE" ) IF oUrl <> NIL THEN dOrdb := dEgaToDat( Alltrim(oUrl:cData) ) … и dOrdb имеет реальное значение, но стоит добавить в XML тэг на кирилице, например [pre2] <?xml version="1.0" encoding="utf-8"?> <ORDER> <DOCUMENTNAME>220</DOCUMENTNAME> <NUMBER>23000B3094059</NUMBER> <DATE>2021-10-18</DATE> <Вася>2021-10-21</Вася> <DELIVERYTIME>00:00</DELIVERYTIME> </ORDER> [/pre2] как в конструкции oUrl := oDoc:findFirst( "DATE" ) oUrl == NIL

Ответов - 13

Dima: AndreyZh пишет: но стоит добавить в XML тэг на кирилице, например Вполне возможно.... Можно попробовать библиотеку Кресина (я её юзаю) HXMLDoc Брать на сайте у него а живет в библе (сырцы) HWGUI

SergKis: AndreyZh У вас данные в utf-8, имена тэгов (два байта для рус. букв), а в классе работа с однобайтными данными в именах тэгов, не смотрел класс TXmlDocument, но думаю причина в этом. Как вариант: 1. составить hash справочник перекодировки тэгов RU => EN 2. прочитать hb_memoread(...xml), ф-ями для работы с utf8 найти по списку hash и заменить на EN тэги 3. сохранить hb_memwrit(...new.xml,...) 4. потом обработать классом TXmlDocument 5. Если надо использовать названия тэгов на рус. яз. сделать обратные действия по hash, заменив EN на RU Другой вариант, взять файл xml редактором с кодовой страницей utf-8, Ctrl+A, Ctrl+C и перенести в редактор с кодовой страницей 1251 Ctrl+V, сохранить и обработать классом TXmlDocument по вашему примеру выше. Dima пишет Можно попробовать библиотеку Кресина (я её юзаю) HXMLDoc Думаю не поможет, там парсинг на C и наверно исп. однобайтная работа с тэгами

Dima: SergKis +1


AndreyZh: SergKis спасибо! Буду думать, хотя и такой подход не совсем нравится. Что по кодировке - написал, что в любой, т.к. изначально "пляски" начались от электронного УПД, что в формате 1251... и весь электронный государственный документооборот в хмл файла с тегах на кирилице

SergKis: AndreyZh пишет весь электронный государственный документооборот в хмл файла с тегах на кирилице Зачем тогда <?xml version="1.0" encoding="utf-8"?> Используйте <?xml version="1.0" encoding="1251"?> (не помню, как правильно) или напишите перекодировку из utf-8 => Ru1251, т.е. перезапись файла, что то типа такого cOld := hb_cdpSelect( "UTF8" ) cBuf := hb_memoread(...xml) IF left(cBuf, 3) == hb_utf8Chr( 0xFEFF ) ; cBuf := subs( cBuf, 4 ) ENDIF hb_memowrit( ...new.xml, hb_Utf8ToStr(cBuf, "RU1251") ) hb_cdpSelect( cOld )

SergKis: PS. Для HXMLDoc от А.Кресина можно так делать (CODEPAGE стоит RU1251)[pre2] cXml := hb_memoread(Xml) If IsUtf8Bom(cXml) cXml := subs(cXml, Len(Utf8Bom())+1) cXml := hb_Utf8ToStr(cXml) ElseIf hb_StrIsUTF8(cXml) cXml := hb_Utf8ToStr(cXml) EndIf oXml := HXMLDoc():Read( , cXml) ... FUNC IsUtf8Bom( cTxt ) LOCAL cBom := hb_utf8Chr( 0xFEFF ) LOCAL lRet := .F. If ! empty(cTxt); lRet := left(cTxt, Len(cBom)) == cBom EndIf RETURN lRet [/pre2]

AndreyZh: SergKis, как отмечал, что сие касается любой кодировки. Фрагмент изначального файла для парсинга: [pre2] <?xml version="1.0" encoding="windows-1251"?> <Файл ВерсПрог="Lera_edi v. 24.10.2019" ВерсФорм="5.01" ИдФайл="ON_NSCHFDOPPR_2LHD826718C-0312-4657-B0A7-E4413957CF8F_2LH64ABCF29-EB18-40C9-9571-0565DD31FA89_20200327_a078b830-26d0-44e2-8aa8-6d10ce82757c"> <СвУчДокОбор ИдОтпр="2LH64ABCF29-EB18-40C9-9571-0565DD31FA89" ИдПол="2LHD826718C-0312-4657-B0A7-E4413957CF8F"> <СвОЭДОтпр ИННЮЛ="7723815417" ИдЭДО="2LH" НаимОрг="ООО &quot;ФораПром&quot;"/> </СвУчДокОбор> <Документ ВремИнфПр="12.08.20" ДатаИнфПр="27.03.2020" КНД="1115131" НаимДокОпр="Счет-фактура и документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)" НаимЭконСубСост="Индивидуальный предприниматель Саркисян Вардан Анзорикович" ПоФактХЖ="Документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)" Функция="СЧФДОП"> <СвСчФакт ДатаСчФ="26.03.2020" КодОКВ="643" НомерСчФ="34801"> <ИспрСчФ ДефДатаИспрСчФ="-" ДефНомИспрСчФ="-"/> <СвПрод ИнфДляУчаст="4607124669999"> <ИдСв> <СвИП ИННФЛ="644901100440" ИныеСвед="4607124669999" СвГосРегИП="304644934500411"> [/pre2] Для меня сие случилось полным нежданчиком, т.к. формирование УПД средствами Harbour с тегами на кирилице проблем никогда не было, например: [pre2] // Создаём первый XML узел описания контрагента. Добавляем в корень дерева oMain := TXmlNode():new( , HB_OEMTOANSI("Контрагенты"), {HB_OEMTOANSI('ИдКонтр') => cReg, HB_OEMTOANSI('П000000000007') => HB_OEMTOANSI(Alltrim(name)) }) oDocument:addBelow(oMain) oPosition := TXmlNode():new( ,HB_OEMTOANSI("Резидент") ) // Тип контейнер oMain:addBelow(oPosition) // Для поставщиков алкогольной продукции отражаем реквизиты лицензии - не пиво и есть лицензия у КА IF (nAlco <> 2) .AND. !Empty(numbLic) oLic := TXmlNode():new( ,HB_OEMTOANSI("Лицензии") ) // Тип контейнер oPosition:addBelow(oLic) // Описание лицензии в составном тэге oUrl := TXmlNode():new( , HB_OEMTOANSI("Лицензия"), {HB_OEMTOANSI('ИдЛицензии') => "7", HB_OEMTOANSI('П000000000011') => HB_OEMTOANSI(Alltrim(serLic))+","+HB_OEMTOANSI(Alltrim(numbLic)), HB_OEMTOANSI('П000000000012') => Dtoc(datLic), HB_OEMTOANSI('П000000000013') => Dtoc(endLic), HB_OEMTOANSI('П000000000014') => HB_OEMTOANSI(Alltrim(kemLic)) }) oLic:addBelow(oUrl) [/pre2]

AndreyZh: Dima пишет: Можно попробовать библиотеку Кресина (я её юзаю) HXMLDoc На сайте Александра есть лишь минимум справки по данной библе, а есть ли где примеры пользования или что-то типа инструкции?

alkresin: Примеры использования есть в hwgui/utils/tutorial/tutor.prg, hwgui/utils/editor/editor.prg, hwgui/utils/designer/designer.prg - функции ReadIni (там ini-файлы в xml-формате). Ну и prg-исходник можно посмотреть, hwgui/source/common/xml/hxmldoc.prg, он небольшой и несложный.

SergKis: AndreyZh пишет есть ли где примеры пользования или что-то типа инструкции? Кусок кода, как есть, чтение xml (Возвратный ордер из магазина) для просмотра в TsBrowse MiniGui, может пригодится [pre2]// Return OrderXml RETANN #include "hmg.ch" #include "TSBrowse.ch" #define XML_DOC_RETURN 'RETANN' #define XML_DOC_TITLE 'Document-ReturnAnnouncement' #define XML_DOC_HEADER 'Document-Header' #define XML_DOC_BUYER 'ReturnAnnouncement-Header' #define XML_DOC_PARTIES 'ReturnAnnouncement-Parties' #define XML_DOC_LINES 'ReturnAnnouncement-Lines' #define XML_DOC_LINE 'Line' #define XML_DOC_ITEM 'Line-Item' #define XML_DOC_SUMMARY 'ReturnAnnouncement-Summary' #define XML_DOC_ID 'DocumentID' #define XML_DOC_TYPE 'DocumentType' #define XML_DOC_NUMBER 'ReturnAnnouncementNumber' #define XML_DOC_DATE 'ReturnAnnouncementDate' #define XML_DOC_LOCATION 'Location' #define XML_DOC_KLICODE 'CodeBySeller' #define XML_DOC_KLINAME 'Name' #define XML_DOC_KLISTREET 'StreetAndNumber' #define XML_DOC_KLIPOSTAL 'PostalCode' #define XML_DOC_KLICOUNTRY 'Country' #define XML_DOC_KLIILN 'ILN' STATIC o_Xml, o_Doc, a_Doku, a_Line, a_Head, a_Body, a_Klie, a_Tags * ----------------------------------------------------------------------------------- * FUNCTION XmlView( oWnd, lLoad ) * ----------------------------------------------------------------------------------- * LOCAL cWnd := 'wXmlReturn', hSpl LOCAL cBrw := 'XmlReturn', oBrw, oCol LOCAL cCapt := 'XML file load' LOCAL cFile := gProp(cXmlFile) LOCAL cFil := subs(cFile, RAt('\', cFile)+1) LOCAL aDatos, aHead, aLine, aFoot, aSize, aPict, aAlign, aName, aFont, aTag, bBlk LOCAL nI, nK, nN, nY, nX, nW, nH, aHe, aLi, aTmp, cTmp, aClr, cCap, aKli, cKli, oKli IF empty(lLoad) ; RETURN Nil ENDIF nK := 11 // Len(a_Head) aHe := array(nK) ; aAlign := array(nK) ; aName := array(nK) aHe[ 1] := 'Line'+CRLF+'Number' ; aAlign[ 1] := 1 ; aName[ 1] := 'NOM' aHe[ 2] := 'EAN' ; aAlign[ 2] := 1 ; aName[ 2] := 'EAN' aHe[ 3] := 'Buyer'+CRLF+'ItemCode' ; aAlign[ 3] := 1 ; aName[ 3] := 'KOD' aHe[ 4] := 'Supplier'+CRLF+'ItemCode' ; aAlign[ 4] := 1 ; aName[ 4] := 'COD' aHe[ 5] := 'Item'+CRLF+'Description' ; aAlign[ 5] := 0 ; aName[ 5] := 'NAM' aHe[ 6] := 'Returned'+CRLF+'Quantity' ; aAlign[ 6] := 1 ; aName[ 6] := 'KOL' aHe[ 7] := 'Return'+CRLF+'Status' ; aAlign[ 7] := 1 ; aName[ 7] := 'RET' aHe[ 8] := 'UnitNet'+CRLF+'Price' ; aAlign[ 8] := 1 ; aName[ 8] := 'CEN' aHe[ 9] := 'UnitOf'+CRLF+'Measure' ; aAlign[ 9] := 1 ; aName[ 9] := 'EDI' aHe[10] := 'ReturnedUnit'+CRLF+'PackSize' ; aAlign[10] := 1 ; aName[10] := 'SIZ' aHe[11] := 'NetAmount' ; aAlign[11] := 1 ; aName[11] := 'SUM' aLine := {} FOR EACH aTmp, aTag IN a_Line, a_Tags aLi := array(nK) ; aFill(aLi, "") ; nN := 0 FOR nI := 1 TO Len(aTmp) IF "LineNumber" $ aTag[ nI ] ; nN := 1 ELSEIF "EAN" $ aTag[ nI ] ; nN := 2 ELSEIF "BuyerItemCode" $ aTag[ nI ] ; nN := 3 ELSEIF "SupplierItemCode" $ aTag[ nI ] ; nN := 4 ELSEIF "ItemDescription" $ aTag[ nI ] ; nN := 5 ELSEIF "ReturnedQuantity" $ aTag[ nI ] ; nN := 6 ELSEIF "ReturnStatus" $ aTag[ nI ] ; nN := 7 ELSEIF "UnitNetPrice" $ aTag[ nI ] ; nN := 8 ELSEIF "UnitOfMeasure" $ aTag[ nI ] ; nN := 9 ELSEIF "ReturnedUnitPackSize" $ aTag[ nI ] ; nN := 10 ELSEIF "NetAmount" $ aTag[ nI ] ; nN := 11 ELSEIF "Remarks" $ aTag[ nI ] ; nN := 11 ENDIF IF nN > 0 ; aLi[ nN ] := aTmp[ nI ] ENDIF NEXT //? hb_enumindex(aTmp), aLi, hb_valtoexp(aLi) aAdd( aLine, aLi ) NEXT aFoot := .T. aFont := { gProp(TsbHeader), gProp(TsbFooter) } aHead := aHe aDatos := { aLine, aHead, aSize, aFoot, aPict, aAlign, aName } DEFINE WINDOW &cWnd ; TITLE ' '+cCapt+' ' ; MDICHILD FOCUSED NOMINIMIZE ; ON INIT NIL ; ON RELEASE NIL ; ON INTERACTIVECLOSE .T. ; //(This.Object):Action ; ON SIZE NIL ; ON MAXIMIZE NIL DEFINE SPLITBOX HANDLE hSpl DEFINE TOOLBAR ToolBar_1 CAPTION " " + upper(cFil) + " " BUTTONSIZE 110,32 FLAT BUTTON 01 CAPTION gTxt(Save) PICTURE 'Save' ACTION wPost() ; TOOLTIP gTxt(Load)+' XML. ' SEPARATOR END TOOLBAR DEFINE TOOLBAR ToolBar_2 CAPTION '' BUTTONSIZE 44,32 FLAT BUTTON 99 CAPTION gTxt(Exit) PICTURE 'exit' ACTION wPost() END TOOLBAR END SPLITBOX nY := GetWindowHeight(hSpl) nX := 1 nW := This.ClientWidth - nX * 2 nH := This.ClientHeight - nY bBlk := {|ob| WITH OBJECT ob AEval( :aColumns, {|oc| oc:nFAlign := 1, ; oc:nWidth *= iif( oc:cName == "NAM", 1.05, 0.9 ) } ) :GetColumn("NOM"):nWidth *= 0.8 :GetColumn("KOL"):cPicture := "999999999" :GetColumn("KOL"):bDecode := {|xv| Val(xv) } :GetColumn("SIZ"):cPicture := "999999999" :GetColumn("SIZ"):bDecode := {|xv| Val(xv) } :GetColumn("CEN"):cPicture := "9999999.99" :GetColumn("CEN"):bDecode := {|xv| Val(xv) } :GetColumn("SUM"):cPicture := "99999999.99" :GetColumn("SUM"):bDecode := {|xv| Val(xv) } :lCellBrw := .T. :nFreeze := 1 :lLockFreeze := .T. :nCell := :nFreeze + 1 :nHeightCell += 2 :nHeightHead += 2 :nHeightFoot := :nHeightCell :ResetVScroll( .T. ) :oHScroll:SetRange( 0, 0 ) :AdjColumns() END WITH Return Nil } oBrw := Brw2Arr( cBrw, nY, nX, nW, nH, aDatos, aClr, aFont, .T., bBlk ) WITH OBJECT oBrw :aBitMaps := { LoadImage("br_empty"), LoadImage("Save") } cTmp := GetDokumVal("TotalReturnedAmount") :GetColumn('SIZ'):cFooting := GetDokumVal("TotalLines") oCol := :GetColumn('KOL') oCol:cFooting := Transform( Val(left(cTmp, Len(cTmp)-1)), oCol:cPicture ) oCol := :GetColumn('SUM') oCol:cFooting := Transform( Val(GetDokumVal("TotalNetAmount")), oCol:cPicture ) cTmp := GetDokumVal("DocumentID") + CRLF + ; GetDokumVal("ReturnAnnouncementNumber") + CRLF + ; GetDokumVal("ReturnAnnouncementDate") cCap := "ID" + CRLF + "Number" + CRLF + "Date" ADD SUPER HEADER TO oBrw FROM 1 TO 2 TITLE cCap COLOR CLR_BLUE ADD SUPER HEADER TO oBrw FROM 3 TO 3 TITLE cTmp COLOR CLR_SLATEBLUE cKli := GetDokumVal("CodeBySeller") cTmp := cKli+CRLF+GetDokumVal("Name")+CRLF+GetDokumVal("StreetAndNumber")+' '+GetDokumVal("PostalCode") ADD SUPER HEADER TO oBrw FROM 4 TO 5 TITLE gTxt(Customer) COLOR CLR_BLUE ADD SUPER HEADER TO oBrw FROM 6 TO 7 TITLE cTmp COLOR CLR_SLATEBLUE cTmp := cKli oKli := U04_Kod2Rec(cKli) IF ! empty(oKli) cTmp += CRLF+alltrim(oKli:R_2)+' '+alltrim(iif( empty(oKli:R_4), oKli:R_5, oKli:R_4 ))+CRLF cTmp += alltrim(oKli:R_2A)+' '+alltrim(oKli:R_3) ENDIF ADD SUPER HEADER TO oBrw FROM 8 TO :nColCount() TITLE cTmp COLOR CLR_BLUE :nHeightSuper += 2 :UserKeys( VK_ESCAPE, {|ob| wPost(99, ob, ob) } ) :SetNoHoles() END WITH (This.Object):Event( 01, {|ow| XmlSave(ow, oBrw, cKli, oKli) } ) (This.Object):Event( 99, {|ow| ow:Release() } ) END WINDOW RETURN Nil * ----------------------------------------------------------------------------------- * FUNCTION KolNoNul( xv ) * ----------------------------------------------------------------------------------- * Local nn, cv If ISNUMERIC(xv) ; xv := hb_ntos(xv) EndIf If ( nn := At(".", xv) ) > 0 cv := subs(xv, nn + 1) If cv == repl("0", len(cv)) xv := left(xv, nn - 1) EndIf EndIf RETURN xv * ----------------------------------------------------------------------------------- * FUNCTION CenNoNul( xv ) * ----------------------------------------------------------------------------------- * Local nn, cv, cc, nk ? valtype(xv), xv If ISNUMERIC(xv) ; xv := hb_ntos(xv) EndIf nk := Len(xv) FOR nn := nk TO 1 STEP -1 cc := subs( xv, nn, 1 ) IF cc == "0" xv := left(xv, nn - 1) + " " ELSE EXIT ENDIF NEXT RETURN trim( xv ) * ----------------------------------------------------------------------------------- * STATIC FUNCTION XmlSave( oWnd, oBrw, cKli, oKli ) * ----------------------------------------------------------------------------------- * LOCAL aSup1, aSup2, aSup3, nWa1, nWa2, cTxt, xVal, nSum LOCAL nWa0 := Select(), oCol, aLine, nI, nK, oC, cNam LOCAL cPth := gProp(PATH) LOCAL cFil := gProp(cXmlFile) LOCAL cXml := hb_FNameName(cFil)+hb_FNameExt(cFil) LOCAL lRet := .T., oRec LOCAL oPub := gPublic() LOCAL aFoot := {} LOCAL nPvnProc := Val(gProp(TAX)) LOCAL cDok := gIniC(gProp(LangFile), [DOK], 'DokumRet') LOCAL cSumNoPvn := gIniC(gProp(LangFile), [DOK], 'SumNoPvn') // надпись из ini.lv LOCAL cSumArPvn := gIniC(gProp(LangFile), [DOK], 'SumArPvn') // надпись LOCAL cPvnProc := gIniC(gProp(LangFile), [DOK], 'PvnProc' ) // надпись LOCAL cKliTxt := gIniC(gProp(LangFile), [KLI], 'Kli' ) LOCAL cOrgTxt := gIniC(gProp(LangFile), [KLI], 'Sanem' ) LOCAL cAdrJur := gIniC(gProp(LangFile), [KLI], 'AdrJur' ) LOCAL cAdrFiz := gIniC(gProp(LangFile), [KLI], 'AdrFiz' ) LOCAL cAdrMst := gIniC(gProp(LangFile), [KLI], 'AdrMst' ) LOCAL cTelefon := gIniC(gProp(LangFile), [KLI], 'Telefon' ) LOCAL cRegNr := gIniC(gProp(LangFile), [KLI], 'RegNr' ) LOCAL cPvnNr := gIniC(gProp(LangFile), [KLI], 'PvnNr' ) LOCAL cBank := gIniC(gProp(LangFile), [KLI], 'Bank' ) LOCAL cBankKod := gIniC(gProp(LangFile), [KLI], 'BankKod' ) LOCAL cBankScet := gIniC(gProp(LangFile), [KLI], 'BankScet') LOCAL aKliBank, cKliBank, cKliBankKod, cKliBankScet IF empty(oKli) lRet := .F. MsgStop(gTxt(NotKod)+CRLF+cKod, gTxt(Customer)) RETURN lRet ENDIF oMain:StatusBar:Say(gTxt(Wait)) WITH OBJECT oBrw aSup1 := hb_ATokens( :cTextSupHdGet(1), CRLF ) aSup2 := hb_ATokens( :cTextSupHdGet(2), CRLF ) aSup3 := hb_ATokens( :cTextSupHdGet(4), CRLF ) aLine := :aArray[1] FOR EACH oC IN :aColumns IF "ARRA" $ oC:cName ; nK := hb_ntos(:nLen) ELSE ; nK := oC:cFooting ENDIF AAdd(aFoot, {oC:cName, iif( Empty(nK), nK, val(nK) )}) NEXT END WITH cKli := TR0(cKli, 4) ; aKliBank := RC_Find(cKli) cKliBank := cKliBankKod := cKliBankScet := "" IF ! Empty(aKliBank) cKliBank := aKliBank[1] // код банка cKliBankKod := aKliBank[2] // наименование cKliBankScet := aKliBank[3] // расч. счет ENDIF /* hb_WAEval({|| msglog(select(), Alias(), OrdCount(), IndexOrd(), OrdSetFocus(), OrdKey() ) }) ? "oKli =", oKli:GetAll(.F.), "<"+cKli+">", "<"+aSup3[1]+">" ?h oKli:GetAll(.F.) ? */ If V08_Use(); nWa1 := Select() EndIf If V09_Use(); nWa2 := Select() EndIf If empty(nWa1) .or. empty(nWa2) lRet := .F. cTxt := gTxt(NotUsed) + CRLF cTxt += iif( nWa1 > 0, '', cPth + 'V08' + '.dbf' ) cTxt += iif( nWa2 > 0, '', CRLF + cPth + 'V09' + '.dbf' ) If nWa1 > 0; (nWa1)->( dbCloseArea() ) EndIf If nWa2 > 0; (nWa2)->( dbCloseArea() ) EndIf oMain:StatusBar:Say('') MsgStop( cTxt, gTxt(Error) ) RETURN lRet EndIf // надо заполнить из SuperHeader табл. xml oRec := V08_Stru(.T.) // oKeyData() oRec:B_0 := cXml // Xml file name REPL B_0 with cXml, ; oRec:B_I := aSup2[1] // <DocumentID> B_I with aSup2[1], ; oRec:B_T := 'RETANN' // <DocumentType>RETANN</DocumentType> B_T with 'RETANN', ; oRec:D_1 := cDok // D_1 with gTxt(Pavadz), ; oRec:D_2 := aSup2[3]+' '+aSup2[2] // D_2 with aSup2[3]+' '+aSup2[2], ; oRec:D_3 := aSup2[2] // <ReturnAnnouncementNumber> номер док. выписаного ранее D_3 with aSup2[2], ; oRec:D_4 := aSup2[3] // <ReturnAnnouncementDate> дата док. ... D_4 with aSup2[3], ; oRec:K_0 := cKli // aSup3[1] // <CodeBySeller> K_0 with aSup3[1], ; oRec:K_1 := cKliTxt // текст: Nosūtītājs --- cKli --- отправитель K_1 with gTxt(CustKli), ; oRec:K_2 := aSup3[2] // наим. клиента из xls K_2 with aSup3[2], ; oRec:K_3 := cRegNr // текст: Reģistrācijas Nr. oRec:K_4 := gArrKli(a_Klie, 'ILN') // RegNr oRec:K_5 := cPvnNr // текст: PVN reģistrācijas Nr. K_3 with gIniKli('RegNr' ), ; oRec:K_6 := oKli:R_4 // PvnNr K_5 with gInkKli('PvnNr' ), ; oRec:K_7 := cAdrJur // текст: Juridiskā adrese K_7 with gInkKli('AdrJur' ), ; oRec:K_8 := oKli:R_3 // AdrJur K_9 with gInkKli('AdrFiz' ), ; oRec:K_9 := cAdrFiz // текст: Preču izsniegšanas vieta: K_B with gIniKli('Telefon' ), ; oRec:K_A := aSup3[3] // AdrFiz K_D with gIniKli('Bank' ), ; oRec:K_B := cTelefon // текст: Tālruņa nr. K_F with gIniKli('BankKod' ), ; //oRec:K_C := // Telefon K_H with gIniKli('BankScet'), ; oRec:K_D := cBank // текст: Banka K_M with gArrKli(a_Klie, 'Name' ), oRec:K_E := cKliBank // Bank K_N with gArrKli(a_Klie, 'StreetAndNumber'), oRec:K_F := cBankKod // текст: Bankas kods K_P with gArrKli(a_Klie, 'PostalCode' ), oRec:K_G := cKliBankKod // BankKod K_S with gArrKli(a_Klie, 'Country' ), oRec:K_H := cBankScet // текст: Bankas konts oRec:K_I := cKliBankScet // BankScet oRec:K_M := gArrKli(a_Klie, 'Name') // <Name> oRec:K_N := gArrKli(a_Klie, 'StreetAndNumber') // <StreetAndNumber> oRec:K_P := gArrKli(a_Klie, 'PostalCode') // <PostalCode> oRec:K_S := gArrKli(a_Klie, 'Country') // <Country> oRec:O_1 := cOrgTxt // текст: Saņēmējs oRec:O_2 := oPub:NameK // OrgName oRec:O_3 := cRegNr // текст: Reģistrācijas Nr. oRec:O_4 := oPub:RegNr // RegNr oRec:O_5 := cPvnNr // текст: PVN reģistrācijas Nr. oRec:O_6 := oPub:PvnNr // PvnNr oRec:O_7 := cAdrJur // текст: Juridiskā adrese oRec:O_8 := oPub:AdrJ // AdrJur oRec:O_9 := cAdrFiz // текст: Preču saņemšanas vieta: oRec:O_A := oPub:AdrF // AdrFiz oRec:O_B := cTelefon // текст: Tālruņa nr. oRec:O_C := oPub:AdrJT // Telefon oRec:O_D := cBank // текст Banka oRec:O_E := oPub:EurBank // Bank oRec:O_F := cBankKod // текст: Bankas kods oRec:O_G := oPub:EurSWIFT // BankKod oRec:O_H := cBankScet // текст: Bankas konts oRec:O_I := oPub:EurIBAN // BankScet oRec:I_1 := cSumNoPvn // текст: Kopā bez PVN EUR //oRec:I_2 := // Summa bez PVN oRec:I_3 := gProp(TAX)+cPvnProc // текст: 21 % PVN //oRec:I_4 := // Summa PVN oRec:I_5 := cSumArPvn // текст: Kopā ar PVN EUR //oRec:I_6 := // Summa oRec:I_7 := Val(gArrKli(a_Doku, 'TotalLines')) // <TotalLines> oRec:I_8 := Val(gArrKli(a_Doku, 'TotalReturnedAmount')) // <TotalReturnedAmount> oRec:I_9 := Val(gArrKli(a_Doku, 'TotalNetAmount')) // <TotalNetAmount> //oRec:I_E1 := // Nr line excel //oRec:I_E2 := // ... //oRec:I_E3 := // ... //oRec:M_1 := // Дата док. //oRec:M_2 := // Nr. док. //oRec:M_3 := // Serija док. oRec:M_4 := cKli // TR0( This.KliKod.Value, 4) oRec:M_5 := oKli:R_2 // This.KliNam.Value oRec:M_6 := oKli:R_4 // Рег.Nr клиента oRec:M_7 := oKli:R_5 // Pvn.Nr клиента oRec:M_8 := oKli:R_13 // Группа клиента //oRec:M_9 := 0 // Счетчик строк с ошибкой передачи в UMZ //oRec:M_10 := 0 // Счетчик строк с ошибкой нет EAN в U02 */ //?h oRec:GetAll(.F.) //? (nWa1)->( dbSeek(oRec:D_2) ) IF oRec:D_2 == (nWa1)->D_2 lRet := .F. oMain:StatusBar:Say('') MsgStop(gTxt(SaveInf) + ' !' + CRLF + oRec:D_2, gTxt(Error)) ELSE Select(nWa1) APPEND BLANK oRecPut(oRec) Select(nWa2) ; OrdSetFocus(0) ; nK := Len( oBrw:aColumns ) oRec := V09_Stru(.T.) oRec:D_2 := (nWa1)->D_2 //aLine := oRec:GetAll() //? oRec:GetAll(); ?v oRec:GetAll(); ? //for ni := 1 to len(aLine) //? ni, aLine[ni][1],valtype(aLine[ni][2]) //next nSum := 0 FOR EACH aLine IN oBrw:aArray nK := hb_enumindex(aLine) FOR nI := 2 TO Len( oBrw:aColumns ) oCol := oBrw:aColumns[ nI ] cNam := oCol:cName xVal := aLine[ nI-1 ] IF cNam == 'NOM' ; oRec:R_0 := ToValue(Valtype(oRec:R_0), xVal) ELSEIF cNam == 'EAN' ; oRec:R_2 := ToValue(Valtype(oRec:R_2), xVal) ELSEIF cNam == 'KOD' ; oRec:R_9 := ToValue(Valtype(oRec:R_9), xVal) ELSEIF cNam == 'COD' ; oRec:R_9C := ToValue(Valtype(oRec:R_9C), xVal) oRec:R_1 := nK ELSEIF cNam == 'NAM' ; oRec:R_3 := ToValue(Valtype(oRec:R_3), xVal) ELSEIF cNam == 'KOL' ; oRec:R_4 := ToValue(Valtype(oRec:R_4), xVal) ELSEIF cNam == 'RET' ELSEIF cNam == 'CEN' ; oRec:R_6 := ToValue(Valtype(oRec:R_6), xVal) ELSEIF cNam == 'EDI' ; oRec:R_5 := ToValue(Valtype(oRec:R_5), xVal) ELSEIF cNam == 'SIZ' ELSEIF cNam == 'SUM' ; oRec:R_7 := ToValue(Valtype(oRec:R_7), xVal) ENDIF NEXT oRec:R_8 := .T. nSum += oRec:R_7 APPEND BLANK oRecPut(oRec) NEXT //(nWa1)->I_6 := nSum (nWa1)->I_2 := nSum (nWa1)->I_4 := Round(nSum * nPvnProc/100, 2) (nWa1)->I_6 := nSum + (nWa1)->I_4 //!!! //(nWa1)->I_2 := nSum + (nWa1)->I_4 //!!! ENDIF (nWa1)->( dbCloseArea() ) (nWa2)->( dbCloseArea() ) Select(nWa0) ; oMain:StatusBar:Say('') oBrw:aSuperHead[ 1, 8 ] := oBrw:aBitMaps[2] ; oBrw:DrawSuper() ; DO EVENTS RETURN lRet * ----------------------------------------------------------------------------------- * FUNCTION XmlLoad( oWnd ) * ----------------------------------------------------------------------------------- * LOCAL cStartPath, lXml := .F. LOCAL cFilter := '*.xml', cTmp LOCAL cTitle := 'Open File XML' LOCAL cPath := gProp(cXmlPth) LOCAL cFile := '', oDoc Default oWnd := ThisWindow.Object cStartPath := iif( empty(cPath), cmCurDir()+'\', cPath ) If right(cStartPath, 1) == '\' ; cStartPath := left(cStartPath, len(cStartPath) - 1) EndIf cFile := GetOpenFileName( cStartPath, cFilter, cTitle, , .F. ) If ! empty(cFile) IF lower(right(cFile, 4)) == subs(cFilter, 2) sProp( cXmlFile, cFile ) Else cTmp := 'The file extension is not .XML !' MsgStop( cTmp + CRLF + CRLF + cFile, gTxt(Error)) cFile := '' Endif Endif sProp(cXmlFile, cFile) IF ! XmlRead2Doc(cFile) ; RETURN .F. ENDIF IF ! XmlDoc2Arr() ; RETURN .F. ENDIF IF GetDokumVal("CodeBySeller") == '?' MsgStop('Not found tag <'+"CodeBySeller"+'>'+' !', 'ERROR') a_Doku := a_Line := NIL RETURN .F. ENDIF RETURN .T. *----------------------------------------------------------------------------* STATIC FUNCTION XmlRead2Doc( Xml ) *----------------------------------------------------------------------------* LOCAL cDoc := XML_DOC_TITLE , oXml, cXml, c, i, j, k, n, t LOCAL aMsg := { "File not found !", "Not found:" } IF empty(Xml) ; RETURN .F. ENDIF IF ! hb_vfExists(Xml) ; MsgStop(aMsg[1]+CRLF+xml, 'ERROR') ; RETURN .F. ENDIF cXml := hb_memoread(Xml) If IsUtf8Bom(cXml) cXml := subs(cXml, Len(Utf8Bom())+1) cXml := hb_Utf8ToStr(cXml) ElseIf hb_StrIsUTF8(cXml) cXml := hb_Utf8ToStr(cXml) EndIf oXml := HXMLDoc():Read( , cXml) IF Empty(oXml) ; MsgStop(aMsg[2]+xml, 'ERROR') ; RETURN .F. ENDIF IF Empty(oXml:aItems) ; MsgStop(aMsg[2]+xml, 'ERROR') ; RETURN .F. ENDIF o_Xml := oXml IF ! IsOrderStru() ; RETURN .F. ENDIF RETURN .T. *----------------------------------------------------------------------------* STATIC FUNCTION IsOrderStru() *----------------------------------------------------------------------------* LOCAL oDoc, oNode, cNode, oVal LOCAL aNode := {}, oHdr , cVar LOCAL cDoc := XML_DOC_TITLE LOCAL oXml := o_Xml LOCAL aMsg := { 'Error structure XML !', 'Not found tag:<', '>', ; 'ERROR', 'Error value tag:<DocumentType> !' } o_Doc := NIL AAdd(aNode, XML_DOC_HEADER ) AAdd(aNode, XML_DOC_LINES ) AAdd(aNode, XML_DOC_SUMMARY) IF empty( oDoc := oXml:find(cDoc) ) MsgStop( aMsg[1]+CRLF+aMsg[2]+cDoc+aMsg[3], aMsg[4] ) RETURN .F. ENDIF FOR EACH cNode IN aNode oNode := oDoc:find(cNode) IF empty(oNode) MsgStop( aMsg[1]+CRLF+aMsg[2]+cNode+aMsg[3], aMsg[4] ) RETURN .F. ENDIF NEXT oHdr := oDoc:find(XML_DOC_HEADER) FOR EACH cVar IN { XML_DOC_ID, XML_DOC_TYPE } IF empty( oVal := oHdr:find(cVar) ) MsgStop( aMsg[1]+CRLF+aMsg[2]+cVar+aMsg[3], aMsg[4] ) RETURN .F. ENDIF IF cVar == XML_DOC_TYPE .and. oVal:aItems[1] != XML_DOC_RETURN MsgStop( aMsg[5]+CRLF+oVal:aItems[1]+' != '+XML_DOC_RETURN, aMsg[4] ) RETURN .F. ENDIF NEXT o_Doc := oDoc RETURN .T. *----------------------------------------------------------------------------* STATIC FUNCTION XmlDoc2Arr() *----------------------------------------------------------------------------* LOCAL oXmlDoc := o_Doc, a, i, n LOCAL aHead, aDoku, aKlie, aLine, aSumm IF empty(oXmlDoc) ; RETURN .F. ENDIF aHead := OrdHeader( oXmlDoc ) aDoku := OrdDokum ( oXmlDoc ) aKlie := OrdKlient( oXmlDoc ) aLine := OrdLines ( oXmlDoc ) aSumm := OrdSumms ( oXmlDoc ) a_Doku := {} a_Head := {} a_Klie := {} a_Line := array(Len(aLine)) a_Tags := array(Len(aLine)) FOR EACH a IN aLine[1] ; AAdd(a_Head, a[1]) NEXT FOR i := 1 TO Len(aLine) a_Line[ i ] := {} a_Tags[ i ] := {} FOR EACH a IN aLine[ i ] AAdd(a_Line[ i ], a[2]) AAdd(a_Tags[ i ], a[1]) NEXT NEXT FOR EACH a IN aHead ; AAdd(a_Doku, { a[1], a[2] }) NEXT FOR EACH a IN aDoku ; AAdd(a_Doku, { a[1], a[2] }) NEXT FOR EACH a IN aKlie ; AAdd(a_Doku, { a[1], a[2] }) ; AAdd(a_Klie, { a[1], a[2] }) NEXT FOR EACH a IN aSumm ; AAdd(a_Doku, { a[1], a[2] }) NEXT /* ? a_Doku, a_Head, a_Line ?h a_Doku ? ?h a_Head ? ?h a_Line ? */ RETURN .T. *----------------------------------------------------------------------------* STATIC FUNCTION OrdHeader( oDoc ) *----------------------------------------------------------------------------* LOCAL oNod := oDoc:find(XML_DOC_HEADER) LOCAL aVal := {} LOCAL cVar, oVal FOR EACH cVar IN { XML_DOC_ID, XML_DOC_TYPE } IF HB_ISOBJECT( oVal := oNod:find(cVar) ) AAdd(aVal, { cVar, oVal:aItems[1] }) ENDIF NEXT RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION OrdDokum( oDoc ) *----------------------------------------------------------------------------* LOCAL oNod := oDoc:find(XML_DOC_BUYER) LOCAL aVal := {} LOCAL cVar, oVal FOR EACH cVar IN { XML_DOC_NUMBER, XML_DOC_DATE } IF HB_ISOBJECT( oVal := oNod:find(cVar) ) AAdd(aVal, { cVar, oVal:aItems[1] }) ENDIF NEXT RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION OrdKlient( oDoc ) *----------------------------------------------------------------------------* LOCAL cVar, oVal, aElem, lKods LOCAL oKli := oDoc:find(XML_DOC_BUYER ) LOCAL oNod := oKli:find(XML_DOC_LOCATION) LOCAL aVal := {} LOCAL aKli := { XML_DOC_KLICODE , ; XML_DOC_KLINAME , ; XML_DOC_KLISTREET , ; XML_DOC_KLIPOSTAL , ; XML_DOC_KLICOUNTRY, ; XML_DOC_KLIILN ; } FOR EACH cVar IN aKli IF HB_ISOBJECT( oVal := oNod:find(cVar) ) AAdd(aVal, { cVar, oVal:aItems[1] }) ENDIF NEXT IF ! empty(aVal) lKods := .F. FOR EACH aElem IN aVal IF aElem[1] == XML_DOC_KLICODE lKods := .T. EXIT ENDIF NEXT IF ! lKods AAdd(aVal, {XML_DOC_KLICODE, '?'}) ENDIF ENDIF RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION OrdLines( oDoc ) *----------------------------------------------------------------------------* LOCAL oNod := oDoc:find(XML_DOC_LINES) LOCAL aVal := {}, aLine, oLine IF ! HB_ISOBJECT( oNod ) ; RETURN aVal ENDIF FOR EACH oLine IN oNod:aItems IF HB_ISOBJECT( oLine ) .and. oLine:Title == XML_DOC_LINE aLine := OrdLineItem(oLine) IF ! empty(aLine) ; AAdd(aVal, aLine) ENDIF ENDIF NEXT RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION OrdLineItem( oLine ) *----------------------------------------------------------------------------* LOCAL oItm := oLine:find(XML_DOC_ITEM) LOCAL aVal := {}, oVal IF ! HB_ISOBJECT( oItm ) ; RETURN aVal ENDIF FOR EACH oVal IN oItm:aItems IF HB_ISOBJECT( oVal ) ; AAdd(aVal, { oVal:Title, oVal:aitems[1] }) ENDIF NEXT RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION OrdSumms( oDoc ) *----------------------------------------------------------------------------* LOCAL oNod := oDoc:find(XML_DOC_SUMMARY) LOCAL aVal := {}, oVal IF ! HB_ISOBJECT( oNod ) ; RETURN aVal ENDIF FOR EACH oVal IN oNod:aItems IF HB_ISOBJECT( oVal ) ; AAdd(aVal, { oVal:Title, oVal:aitems[1] }) ENDIF NEXT RETURN aVal *----------------------------------------------------------------------------* STATIC FUNCTION GetDokumVal( cKey ) *----------------------------------------------------------------------------* LOCAL a, k, c := "" cKey := upper(cKey) FOR EACH a IN a_Doku IF HB_ISARRAY(a) .and. Len(a) > 1 k := a[1] IF HB_ISCHAR(k) .and. upper(k) == cKey c := a[2] EXIT ENDIF ENDIF NEXT RETURN iif( HB_ISCHAR(c), c, "" ) * ----------------------------------------------------------------------------------- * STATIC FUNCTION U04_Kod2Rec( cKod ) * ----------------------------------------------------------------------------------- * LOCAL nRec := U04->( RecNo() ) LOCAL oRec cKod := TR0(alltrim(cKod), Len( U04->R_1 )) U04->( dbSeek( cKod ) ) IF cKod == U04->R_1 ; oRec := U04->( RecGet() ) ENDIF RETURN oRec [/pre2]

SergKis: PS До кучи шаблон xml (их несколько) для формирования и отправки, т.е. шаблон читаю в HXMLDoc и заполняю тэги по выражениям, записанным в них. Если результатом выражения будет "-", то тэг на выход не идет. У вас программный код, у меня шаблоны xml. Для печати (pdf) похожая схема - шаблоны [pre2] <?xml version="1.0" encoding="Utf-8"?> <Document-Invoice> <Document-Header> <DocumentReceiveDateTime>^mDtoS(Date(), "-")+"T"+Time()</DocumentReceiveDateTime> <DocumentProcessDateTime>^-</DocumentProcessDateTime> <DocumentID>^-</DocumentID> <DocumentUID>^-</DocumentUID> <DocumentType>INVOICE</DocumentType> <DocumentSource>W</DocumentSource> <OriginalFileName>^-</OriginalFileName> </Document-Header> <Invoice-Header> <InvoiceNumber>^AllTrim(NR_2)+AllTrim(NR_1)</InvoiceNumber> <InvoiceDate>^mDtoS(Date(), "-")</InvoiceDate> <InvoiceCurrency>^OH_3</InvoiceCurrency> <InvoicePaymentDueDate>^mDtoS(Date()+10, "-")</InvoicePaymentDueDate> <InvoicePaymentTerms>10</InvoicePaymentTerms> <InvoicePostDate>^-</InvoicePostDate> <DocumentFunctionCode>O</DocumentFunctionCode> <DocumentNameCode>380</DocumentNameCode> <Remarks>^GetFile("txt_remarks.txt",.T.)</Remarks> <Order> <BuyerOrderNumber>^OH_1</BuyerOrderNumber> <BuyerOrderDate>^OH_2</BuyerOrderDate> <SellerOrderNumber>^-</SellerOrderNumber> </Order> <Delivery> <DeliveryLocationNumber>^OP_9</DeliveryLocationNumber> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <Name>^-</Name> <StreetAndNumber>^-</StreetAndNumber> <CityName>^-</CityName> <Country>^-</Country> <DeliveryDate>^mDtoS(Date(), "-")</DeliveryDate> <DespatchNumber>^AllTrim(NR_2)+AllTrim(NR_1)</DespatchNumber> </Delivery> </Invoice-Header> <Document-Parties> <Sender> <ILN>^OP_6</ILN> </Sender> <Receiver> <ILN>^OP_1</ILN> </Receiver> <Creator> <SystemUniqueCode>^-</SystemUniqueCode> <Name>^-</Name> <E-mail>^-</E-mail> <CreationType>^-</CreationType> </Creator> </Document-Parties> <Invoice-Parties> <Buyer> <ILN>^OP_1</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^gT("StreetR")</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Buyer> <Payer> <ILN>^OP_1</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^gT("StreetR")</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Payer> <Invoicee> <ILN>^OP_1</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^gT("StreetR")</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Invoicee> <Seller> <ILN>^OP_6</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^gT("StreetB")</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> <OperatorDetails> <Name>^-</Name> <TelephoneNumber>^-</TelephoneNumber> <E-mail>^-</E-mail> </OperatorDetails> </Seller> <Payee> <ILN>^OP_6</ILN> <TaxID>^-</TaxID> <AccountNumber>^-</AccountNumber> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <Name>^-</Name> <StreetAndNumber>^gT("StreetB")</StreetAndNumber> <CityName>^-</CityName> <Country>^-</Country> </Payee> </Invoice-Parties> <Invoice-Lines> <Line> <Line-Item> <LineNumber>^u2s(LN_1)</LineNumber> <EAN>^AllTrim(LN_2)</EAN> <SupplierItemCode>^-</SupplierItemCode> <ItemDescription>^LN_13</ItemDescription> <InvoiceQuantity>^iif(empty(LN_14), LN_7, LN_14)</InvoiceQuantity> <InvoiceUnitNetPrice>^iif(empty(LN_15), LN_10, LN_15)</InvoiceUnitNetPrice> <UnitOfMeasure>^LN_24</UnitOfMeasure> <InvoicedUnitPackSize>^-</InvoicedUnitPackSize> <TaxRate>^LN_22</TaxRate> <TaxCategoryCode>S</TaxCategoryCode> <TaxAmount>^LN_23</TaxAmount> <NetAmount>^iif(empty(LN_16), LN_11, LN_16)</NetAmount> </Line-Item> <Line-Delivery> <DeliveryLocationNumber>^OP_9</DeliveryLocationNumber> <CodeByBuyer>^-</CodeByBuyer> <Name>^-</Name> <DeliveryDate>^mDtoS(Date()+10, "-")</DeliveryDate> <DespatchNumber>^AllTrim(NR_2)+AllTrim(NR_1)</DespatchNumber> </Line-Delivery> <Line-AdditionalInformation> <CountryOfOrigin>^-</CountryOfOrigin> </Line-AdditionalInformation> </Line> </Invoice-Lines> <Invoice-Summary> <TotalLines>^OS_7</TotalLines> <TotalNetAmount>^OS_6</TotalNetAmount> <TotalTaxAmount>^OS_4</TotalTaxAmount> <TotalRounding>^-</TotalRounding> <TotalGrossAmount>^OS_6+OS_4</TotalGrossAmount> <Tax-Summary> <Tax-Summary-Line> <TaxRate>^OS_5</TaxRate> <TaxCategoryCode>S</TaxCategoryCode> <TaxAmount>^OS_4</TaxAmount> <TaxableAmount>^OS_6</TaxableAmount> </Tax-Summary-Line> </Tax-Summary> </Invoice-Summary> </Document-Invoice>[/pre2] Это мой давний опыт работы с xml PS. Секция <Invoice-Lines> - организует цикл вывода по детальным строкам документа

AndreyZh: alkresin SergKis большое спасибо! Потом буду обязательно изучать, т.к. ограничения штатных средств критичны... а пока нашел примитивное универсальное решение для моей конкретной задачи [pre2] * -------------------------------------------------------------------------------------------------- * Извлечение информации по шаблону из строки, содержащий весь документ. Полагаем, что шаблон типа: * teg="инфа", т.е. информация заключена точно между кавычками * cStr Строка для поиска инфы * cTeg Ключевой тэг * nBeg Стартовое положение в строке для поиска STAT FUNC cReadTeg(cStr,cTeg,nBeg) LOCA cRet:="", ns:=0, nb:=0, ne:=0, cC:="" cStr := Subs(cStr,nBeg) // Выделяю область для поиска первого вхождения // Выходим, если тэг не найден IF (ns:=At(cTeg,cStr)) <= 0 THEN RETU "" cStr := Subs(cStr,ns) IF (ns:=At('="',cStr)) <= 0 THEN RETU "" // Извлекаю нужное содержимое, находящееся между кавычками cRet := Token( Subs(cStr,ns+2), '"', 1 ) RETU cRet [/pre2]

SergKis: SergKis пишет шаблон xml (их несколько) для формирования и отправки, т.е. шаблон читаю в HXMLDoc и заполняю тэги по выражениям Делаю это таким кодом (когда заказ , тоже xml, обработан, по нему формируется xml счет для оплаты) [pre2] FUNCTION Dokum_Invoice( Fil ) LOCAL c,d,e,f,i,j,k,p,cOut,ret := .F.,xml := ".\OrderInv.xml" PRIV nH,oXml cOut := Fil oXml := HXMLDoc():Read( Xml ) IF Empty( oXml:aItems ); RETURN .F. ENDIF p := upper(AllTrim(gIniC7(cFileIni, "COM", "PathINV", ".\XML_INVOICE" ))) p := iif(right(p, 1) == "\", subs(p, 1, len(p)-1), p) c := "Invoice" f := cDir+c+".xml" DirMake(p) fErase(f) IF ( nH := fCreate(f, 0) ) <= 0; RETURN .F. ENDIF fWrite(nH, '<?xml version="1.0" encoding="Utf-8"?>'+hb_OsNewLine()) IF mDbUse(Fil, "ORD") cOut := AllTrim(NR_1) ret := .T. sele ORD dbGoTop() j := "Invoice-Lines" d := "Invoice-Summary" e := "Document-Invoice" Invoice_Head(j) fWrite(nH, "<"+j+">"+hb_OsNewLine()) dbSkip(1) DO WHILE ! EOF() IF empty(LN_0); Invoice_Body(j, d) ENDIF sele ORD dbSkip(1) ENDDO fWrite(nH, "</"+j+">"+hb_OsNewLine()) sele ORD dbGoTop() Invoice_Foot(d, e) fWrite(nH, "</"+e+">"+hb_OsNewLine()) mDbUse(, "ORD") ENDIF fClose(nH) IF ret j := bkRn0("#"+cExe+"f2f.exe -c "+f+" "+p+"\"+c+"_"+cOut+".xml", 0) IF ! empty(j); ret := .F. ENDIF ENDIF fErase(f) RETURN ret ... FUNCTION Invoice_Head( cStop ) LOCAL i,j,k,oXmlD,oXmlN FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems[ i ] fWrite(nH, "<"+oXmlD:title+">"+hb_OsNewLine()) IF ! empty(oXmlD:aItems) FOR k := 1 TO len(oXmlD:aItems) oXmlN := oXmlD:aItems[ k ] IF oXmlN:title == cStop; RETURN .T. ENDIF fWrite(nH, "<"+oXmlN:title+">"+hb_OsNewLine()) GetPut_Node(oXmlN) fWrite(nH, "</"+oXmlN:title+">"+hb_OsNewLine()) NEXT ENDIF fWrite(nH, "</"+oXmlD:title+">"+hb_OsNewLine()) NEXT RETURN .F. FUNCTION Invoice_Body( cStart, cStop ) LOCAL i,j,k,oXmlD,oXmlN FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems[ i ] IF ! empty(oXmlD:aItems) FOR k := 1 TO len(oXmlD:aItems) oXmlN := oXmlD:aItems[ k ] IF oXmlN:title == cStart; GetPut_Node(oXmlN) ELSEIF oXmlN:title == cStop; RETURN .T. ENDIF NEXT ENDIF NEXT RETURN .F. FUNCTION Invoice_Foot( cStart, cStop ) LOCAL i,j,k,oXmlD,oXmlN fWrite(nH, "<"+cStart+">"+hb_OsNewLine()) FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems[ i ] IF ! empty(oXmlD:aItems) FOR k := 1 TO len(oXmlD:aItems) oXmlN := oXmlD:aItems[ k ] IF oXmlN:title == cStart; GetPut_Node(oXmlN) ELSEIF oXmlN:title == cStop; RETURN .T. ENDIF NEXT ENDIF NEXT fWrite(nH, "</"+cStart+">"+hb_OsNewLine()) RETURN .F. FUNCTION GetPut_Node( oNode, uTeg ) LOCAL b,i,j,k,l,t,u,c := valtype(uTeg) k := len(oNode:aItems) FOR i := 1 TO k u := oNode:aItems[ i ] t := Valtype(u) IF t == "C" l := .T. IF subs(u, 1, 1) == "^" l := ! u == "^-" IF l u := subs(u, 2) IF ! empty(u) b := &( "{||"+u+"}" ) u := Str2Html(AllTrim(u2s(Eval(b)))) ENDIF ENDIF ENDIF IF l IF c == "C"; u := "<"+uTeg+">"+u+"</"+uTeg+">"+hb_OsNewLine() ENDIF fWrite(nH, u) ENDIF ELSEIF t == "O" j := IsTeg_Node(u) IF j; fWrite(nH, "<"+u:title+">"+hb_OsNewLine()) ENDIF GetPut_Node(u, u:title) IF j; fWrite(nH, "</"+u:title+">"+hb_OsNewLine()) ENDIF ENDIF NEXT RETURN FUNCTION IsTeg_Node( oNode ) RETURN ( valtype(oNode:aItems[1]) == "O" ) ... [/pre2]



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