Форум » [x]Harbour » XML формирование по образцу , шаблону » Ответить

XML формирование по образцу , шаблону

Vlad04: Как из XML перенести данные в таблицу рассмотрели, получилось просто (при одинаковой структуре) и почти универсально для различных файлов. Сейчас задача сформировать XML по образцу или шаблону. До этого делал - печать в текстовый файл. Уж очень муторно. XML все усложняются , множество условий, циклов . Может кто выложит небольшой самодостаточный пример.

Ответов - 15

Vlad04: И ещё. Готовой базы нет , с которой я формирую XML. По ходу формирования данные дергаю из разных таблиц.

SergKis: Такой пример шаблона пойдет ? [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>^OH_2</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()+10, "-")</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>^-</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Buyer> <Payer> <ILN>^OP_1</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^-</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Payer> <Invoicee> <ILN>^OP_1</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^-</StreetAndNumber> <CityName>^-</CityName> <PostalCode>^-</PostalCode> <Country>^-</Country> </Invoicee> <Seller> <ILN>^OP_6</ILN> <TaxID>^-</TaxID> <CodeBySeller>^-</CodeBySeller> <CodeByBuyer>^-</CodeByBuyer> <UtilizationRegisterNumber>^-</UtilizationRegisterNumber> <Name>^-</Name> <StreetAndNumber>^-</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>^-</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, только в тегах macro выражения, для формирования xml, читаешь его и гонишь на выход по базе. macro ^- это возможность отсутсвия тега, остальное прозрачно. Цветом выделены теги цикла

Vlad04: Шаблон любой пойдет. Немножко кода добавь, что бы было понятно 1) Читаем шаблон Как создаем выходной и макросы типа ^OS_5 - это что

Vlad04: К примеру <ILN>^OP_1</ILN> <TaxID>^-</TaxID> ^OP_1 это ДАТА нода ILN . А ^OP_1 - так у тебя функция называется , которая вычисляет собственно данные ? А если данные несколько строк должно быть.

SergKis: За признаком ^ идет выражени, между тегами (<...>^макро</...>) Значение ^- (наипсаное прямо или полученное после макро) означает запрет вывода тега на выход. OP_1 и т.д. - это имена полей базы тек. алиаса. Тут кусочек prg [pre2] // читаем шаблон и форм. выход FUNCTION Invoice_Crt( 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 _Umz_Open(Fil, Fil) // открываем базу[ы] sele LST IF Fnd_Order(Fil) 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()) ENDIF ENDIF _Umz_Close() // закрыли базу fClose(nH) RETURN ret FUNCTION Invoice_Head( cStop ) LOCAL i,j,k,oXmlD,oXmlN FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems 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 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 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 Invoice_xml( Xml ) LOCAL a := select(),i,j,k,oXml,oXmlD,oXmlN oXml := HXMLDoc():Read( Xml ) IF Empty( oXml:aItems ); RETURN .F. ENDIF FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems fWrite(nH, "<"+oXmlD:title+">"+hb_OsNewLine()) IF ! empty(oXmlD:aItems) FOR j := 1 TO len(oXmlD:aItems) oXmlN := oXmlD:aItems[j] fWrite(nH, "<"+oXmlN:title +">"+hb_OsNewLine()) mbklog(,"<"+oXmlN:title +">") GetPut_Node(oXmlN) fWrite(nH, "</"+oXmlN:title+">"+hb_OsNewLine()) NEXT ENDIF fWrite(nH, "</"+oXmlD:title+">"+hb_OsNewLine()) NEXT fClose(nH) RETURN .T. 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 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(Eval(b))) l := ! u == "^-" 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]

SergKis: Повторю текст (пропустил наличие [ i ]) [pre2] // читаем шаблон и форм. выход FUNCTION Invoice_Crt( 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 _Umz_Open(Fil, Fil) // открываем базу[ы] sele LST IF Fnd_Order(Fil) 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()) ENDIF ENDIF _Umz_Close() // закрыли базу fClose(nH) 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 Invoice_xml( Xml ) LOCAL a := select(),i,j,k,oXml,oXmlD,oXmlN oXml := HXMLDoc():Read( Xml ) IF Empty( oXml:aItems ); RETURN .F. ENDIF FOR i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems[ i ] fWrite(nH, "<"+oXmlD:title+">"+hb_OsNewLine()) IF ! empty(oXmlD:aItems) FOR j := 1 TO len(oXmlD:aItems) oXmlN := oXmlD:aItems[ j ] fWrite(nH, "<"+oXmlN:title +">"+hb_OsNewLine()) mbklog(,"<"+oXmlN:title +">") GetPut_Node(oXmlN) fWrite(nH, "</"+oXmlN:title+">"+hb_OsNewLine()) NEXT ENDIF fWrite(nH, "</"+oXmlD:title+">"+hb_OsNewLine()) NEXT fClose(nH) RETURN .T. 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(Eval(b))) // в utf8 первод l := ! u == "^-" 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] Работаю с xml так: 1. фирма поставляющая xml (заказы) и получающая их (выполнение) xml обратно дает описание их (много штук), структуры их как правило (вход->выход) одинаковые 2. беру xml на входе составляю привязку тегов к базе (таблицам, структурам, алгоритмы). По ней съдаются xml в базу 3. для выхода составляю шаблоны (как выше)

SergKis: Vlad04 пишет А если данные несколько строк должно быть. <Remarks>^GetFile("txt_remarks.txt",.T.)</Remarks> это пример тега с текстом (многострочного если надо)

Vlad04: SergKis Вы используете oXml := HXMLDoc():Read( Xml ) Я в XHARBOUR использовал TXmlDocument(), но он не понимает :aItems

SergKis: Vlad04 Я использовал из hwgui А.Кресина, с xHb не знаком (стоит только для сборки летодб старой версии) HWGUI\source\common\xml\*.*

Vlad04: В МиниГуи c:\MiniGUI\SOURCE\HbXML\ эта же библиотека

Vlad04: ссылка Собрал простой пример, ругается на title

Vlad04: Непонятки какие-то с XML.Пример , который нормально работал на xHarbour build 1.0.0 Intl на xHarbour 1.2.3 Intl. (SimpLex) (Build 20170215) собирается без замечаний , но ничего не отрабатывает

Pasha: Собрал простой пример, ругается на title Непонятна конструкция: for i := 1 TO len(oXml:aItems) oXmlD := oXml:aItems наверное, подразумевалось: oXmlD := oXml:aItems[ i ]

Vlad04: наверное, подразумевалось: oXmlD := oXml:aItems[ i ] Наверно

Vlad04: Стало яснее с библиотеками , работающими с XML В МиниГуи , Харбор - hbxml.lib В хХарбор - TXmlDocument (достаточно известная и распространенная библиотека) есть ещё mxml



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