Hi guys!
I want to post all functions working with posted XML sample.
Maybe it will be useful for someone.
A bug in
mxmlGetText function still exists, this function does not return whole element text value, only first word, but, I've replaced it with
StripTag function defined below.
Code: Select all
*------------------------
function ImportujKursyWalut
param cPlikTabela
LOCAL xml
if hb_FileExists( cPlikTabela)
xml := simplexml_load_file(cPlikTabela )
else
return .f.
endif
if s_mxml_error
MsgStop("Błąd w xml", "hbmxml:", s_mxml_error_msg, hb_eol() )
else
msgdebug(cPlikTabela,asXML(xml))
endif
return .t.
*----------------------
STATIC PROCEDURE my_mxmlError( cErrorMsg )
s_mxml_error_msg := cErrorMsg
s_mxml_error := .T.
RETURN
*----------------------
function simplexml_load_file
param cFileName
return mxmlLoadString( NIL, hb_MemoRead( cFileName ), @type_callback() )
// I don't know why below line does not work fine, returning all elements empty
//RETURN mxmlLoadString( NIL, hb_MemoRead( cFileName ), MXML_TEXT_CALLBACK )
*----------------------
function asXML( xml )
local cText := "", c
local nElementType := 0
local xTabela, xmlElement, xmlPozycja, xmlElementPozycji
local aWaluty := {}
local aPozycja := {}
// z dokumentacji - wyszukiwanie jesli podamy attr lub value to ograniczamy szukanie
//node = mxmlFindElement(tree, tree, "name","attr", "value",MXML_DESCEND);
xTabela := mxmlFindElement( xml, xml, "tabela_kursow", NIL, NIL, MXML_DESCEND )
if empty( xTabela )
return nil
endif
c_Tabela_Kursow_typ := mxmlElementGetAttr( xTabela, "typ" )
c_Tabela_Kursow_uid := mxmlElementGetAttr( xTabela, "uid" )
xmlElement := mxmlGetFirstChild( xTabela )
do while .t.
if mxmlGetType( xmlElement ) == MXML_ELEMENT
cElementName := lower(mxmlGetElement( xmlElement ))
do case
case cElementName == "numer_tabeli"
nElementType := MXML_TEXT
c_numer_tabeli := mxmlGetText(xmlElement, @nElementType)
case cElementName == "data_publikacji"
nElementType := MXML_TEXT
c_data_publikacji := mxmlGetText(xmlElement, @nElementType)
d_data_publikacji := stod(strtran(c_data_publikacji, "-",""))
case cElementName == "pozycja"
aPozycja := { }
//xmlPozycja := mxmlFindElement( xmlElement, xml, "pozycja", NIL, NIL, MXML_DESCEND )
//if !empty(xmlPozycja)
xmlElementPozycji := mxmlGetFirstChild( xmlElement )
do while .t.
cElementName := lower(mxmlGetElement( xmlElementPozycji ))
do case
case cElementName == "nazwa_waluty"
nElementType := MXML_TEXT
// it can't be used to string fields because of bug in mxml library, I think
//c_nazwa_waluty := mxmlGetText(xmlElementPozycji, @nElementType)
// but solution posted by Rathinagiri' solution works almost perfect
c_nazwa_waluty := striptag(mxmlSaveAllocString( xmlElementPozycji, MXML_NO_CALLBACK ), 'nazwa_waluty')
case cElementName == "przelicznik"
nElementType := MXML_TEXT
n_przelicznik := val( mxmlGetText(xmlElementPozycji, @nElementType) )
case cElementName == "kod_waluty"
nElementType := MXML_TEXT
c_kod_waluty := mxmlGetText(xmlElementPozycji, @nElementType)
case cElementName == "kurs_sredni"
nElementType := MXML_TEXT
//conversion to real type of value
n_kurs_sredni := val( strtran( mxmlGetText(xmlElementPozycji, @nElementType), "," , "."))
endcase
if Empty( xmlElementPozycji := mxmlGetNextSibling( xmlElementPozycji ) )
exit
endif
enddo
aAdd(aWaluty, { c_kod_waluty, c_nazwa_waluty, n_przelicznik, n_kurs_sredni } )
//endif
endcase
endif
if Empty( xmlElement := mxmlGetNextSibling( xmlElement ) )
exit
endif
enddo
msgdebug(c_Tabela_Kursow_typ, c_Tabela_Kursow_uid, c_numer_tabeli, c_data_publikacji, d_data_publikacji, len(aWaluty), aWaluty)
RETURN {c_Tabela_Kursow_typ, c_Tabela_Kursow_uid, c_numer_tabeli, c_data_publikacji, d_data_publikacji, len(aWaluty), aWaluty}
/*
* 'type_callback()' - XML data type callback for mxmlLoadFile()...
*/
/* O - Data type */
/* I - Element node */
FUNCTION type_callback( hNode )
LOCAL cType /* Type string */
/*
* You can lookup attributes and/or use the element name, hierarchy, etc...
*/
IF Empty( cType := mxmlElementGetAttr( hNode, "type" ) )
cType := mxmlGetElement( hNode )
if ctype = "nazwa_waluty"
altd()
endif
ENDIF
SWITCH Lower( cType )
CASE "integer" ; RETURN MXML_INTEGER
CASE "opaque" ; RETURN MXML_OPAQUE
CASE "real" ; RETURN MXML_REAL
ENDSWITCH
RETURN MXML_TEXT
*-------------------
function striptag( cStr, cTag )
local nEnd
local nStart
nStart := at('>', cStr )+1
nEnd := rat( '<', cStr )
nCount := nEnd-nStart
//remember to repair this line, because of forum defect!
cStr := s_ubstr(cStr, nStart, nEnd-nStart)
return cStr