Serializar objeto para XML

Olá há algo equivalente ao FWJsonSerialize para XML?

Estou consumindo uma API da Umovme e eles não tem suporte ao json, logo ao invés de serializar um objeto json usando a função FWJsonSerialize preciso serializar um xml, mas não encontrei em nenhum lugar se há uma função equivalente.

Bom dia Adriano, você tem um objeto XML e deseja transformar o mesmo em string, seria isso?


class Medico

	method new() constructor

	data codigo as string init ''
	data nome as string init ''
	data apelido as string init ''

	method setCodigo(codigo)
	method setNome(nome)
	method setApelido(apelido)

endclass

method new() class Medico
return(self)

Depois de instanciar essa classe acima com oMedicos := Medico():New() e fazer devidas atribuições das propriedades, podemos gerar um json com cJson := FWJsonSerialize(oMedicos).
Então, o que quero é ao invés de gerar um json como demonstrei, quero uma string cXML.
Consegui explicar?

Quero evitar o CornoJob de ficar concatenando string pra montar a string xml completa:


cBody := "data="
cBody += "<customEntityEntry>"
cBody += "<description>API REST CLIENTE</description>"
cBody += "<alternativeIdentifier>000480</alternativeIdentifier>"
cBody += "<customFields>"
cBody += "<cnpj>68668045000172</cnpj>"
cBody += "<razao>empresa teste</razao>"
cBody += "<bairro>SANTA CRUZ</bairro>"
cBody += "<cidade>RIO DE JANEIRO</cidade>"
cBody += "</customFields>"
cBody += "</customEntityEntry>"

Estou integrando com a api do Umovme e essa misera não aceita json.

Adriano, bom dia.

Veja se o XMLParser te atende.

https://tdn.totvs.com/display/tec/XmlParser

Fora ele tem outras funções de XML que as vezes te atenda.

https://tdn.totvs.com/display/tec/Tratamento+de+XML

XMLParse não atende porque ela transforma uma string(cXml) para um objeto.
O que eu preciso é serializar um objeto(Model) para o formato xml. Para não ter que ficar concatenando string pra montar a string cXml na mão, sacou?

Boa noite Adriano,

Não existe nada documentado que permita você efetua essa serialização.

O que você pode fazer, é generalizar uma classe que faz a serialização de suas propriedades, artifício que por exemplo o MVC do Protheus utiliza, por isso você consegue trabalhar com o REST do FWModel tanto com JSON quanto com XML.

Essa serialização é feita utilizando a função ClassDataArr:

https://tdn.totvs.com/display/tec/ClassDataArr

E também com base na GetClassName:

https://tdn.totvs.com/display/tec/GetClassName

Abaixo um exemplo de como isso é implementado:


#include "protheus.ch"

//-------------------------------------------------------------------
/*/{Protheus.doc} DnlXmlSerialize
Classe genérica para converter os atributos em xml

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
class DnlXmlSerialize from longnameclass
    method toXml()
    method getValoresObjeto(oObjeto)
    method getValorArray(aArray)
    method getValor(xValue)
endclass

//-------------------------------------------------------------------
/*/{Protheus.doc} toXml
Converte a instancia da classe em xml

@return cXML classe serializada em formato xml

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method toXml() class DnlXmlSerialize
local cXml as char

cXml := '<?xml version="1.0"?>'
cXml += self:getValoresObjeto(self)

return cXml

//-------------------------------------------------------------------
/*/{Protheus.doc} getPropriedades
Método auxiliar ao toXml que converte as propriedades em xml

@param oObjeto Objeto que será convertido

@return cXML XML das propriedades do objeto recebido

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method getValoresObjeto(oObjeto) class DnlXmlSerialize
local aPropriedades as array
local cClasse as char
local cXml as char
local cValor as char
local nI as numeric

aPropriedades := ClassDataArr(oObjeto, /*lParent*/)
cClasse := GetClassName(oObjeto)
cXml := "<" + cClasse + ">"

for nI := 1 to Len(aPropriedades)
    cXml += "<" + aPropriedades[nI][1] + ">"
    cValor := self:getValor(aPropriedades[nI][2])
    cXml += cValor + "</" + aPropriedades[nI][1] + ">"
next

cXml += "</" + cClasse + ">"

aSize(aPropriedades, 0)

return cXml

//-------------------------------------------------------------------
/*/{Protheus.doc} getPropriedades
Método auxiliar ao toXml que converte uma propriedade do tipo array

@param aArray Array que será convertido

@return cValor XML das posições do array recebido

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method getValorArray(aArray) class DnlXmlSerialize
local cValor as char
local nI as numeric

cValor := ""

for nI := 1 to len(aArray)
    cValor += self:getValor(aArray[nI]) + ","
next

cValor := Left( cValor, Len( cValor ) - 1 )

return cValor

//-------------------------------------------------------------------
/*/{Protheus.doc} getValor
Método auxiliar ao toXml que converte o valor da propriedade em string

@param xValue Valor que será convertido

@return cValor XML do valor recebido

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method getValor(xValue) class DnlXmlSerialize
local cValor as char
local cTipo as char

cTipo := ValType(xValue)

do case
    case cTipo == "C"
        cValor := xValue
    case cTipo == "D"
        cValor := DtoC(xValue)
    case cTipo == "B"
        cValor := GetCBSource(xValue)
    case cTipo == "N"
        cValor := cValToChar(xValue)
    case cTipo == "L"
        cValor := Iif(xValue, "true", "false")
    case cTipo == "J"
        cValor := xValue:toJSON()
    case cTipo == "A"
        cValor := self:getValorArray(xValue)
    case cTipo == "O"
        cValor := self:getValoresObjeto(xValue)
    otherwise
        cValor := ""
endcase

return cValor

//-------------------------------------------------------------------
/*/{Protheus.doc} DnlPessoa
Classe simples para exemplificar uma pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
class DnlPessoa from DnlXmlSerialize
    data nome as char
    data sobrenome as char
    data nascimento as date
    data informacoes as array
    data filhos as array

    method new() constructor
    method destroy()

    method setNome(nome)
    method setSobrenome(sobrenome)
    method setNascimento(dNascimento)
    method addInformacao(cInformacao)
    method addFilho(oFilho)
endclass

//-------------------------------------------------------------------
/*/{Protheus.doc} new
Método construtor da classe

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method new() class DnlPessoa
self:nome := ""
self:sobrenome := ""
self:nascimento := CtoD("")
self:informacoes := {}
self:filhos := {}
return self

//-------------------------------------------------------------------
/*/{Protheus.doc} destroy
Método destrutor da classe

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method destroy() class DnlPessoa
local nI as numeric

for nI := 1 to len(self:filhos)
    self:filhos[nI]:destroy()
    FreeObj(self:filhos[nI])
next

aSize(self:informacoes, 0)
aSize(self:filhos, 0)

self:nome := nil
self:sobrenome := nil
self:nascimento := nil
self:informacoes := nil
self:filhos := nil

return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} setNome
Set da propriedade nome

@param cNome Nome da pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method setNome(cNome) class DnlPessoa
self:nome := cNome
return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} setSobrenome
Set da propriedade sobrenome

@param cSobrenome Sobrenome da pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method setSobrenome(cSobrenome) class DnlPessoa
self:sobrenome := cSobrenome
return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} setNascimento
Set da propriedade nascimento

@param dNascimento Nascimento da pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method setNascimento(dNascimento) class DnlPessoa
self:nascimento := dNascimento
return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} addInformacao
Add da propriedade informacoes

@param cInformacao Informação sobre a pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method addInformacao(cInformacao) class DnlPessoa
aAdd(self:informacoes, cInformacao)
return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} addInformacao
Add da propriedade filho

@param oFilho Filho da pessoa

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
method addFilho(oFilho) class DnlPessoa
aAdd(self:filhos, oFilho)
return nil

//-------------------------------------------------------------------
/*/{Protheus.doc} dnlObjToXml
Função para teste da serialização de objetos para XML

@author Daniel Mendes
@since 25/09/2019
@version 1.0
/*/
//-------------------------------------------------------------------
user function dnlObjToXml()
local oDaniel as object
local oRafael as object

oDaniel := DnlPessoa():New()

oDaniel:setNome("Daniel")
oDaniel:setSobrenome("Mendes")
oDaniel:setNascimento( CtoD("10/12/1986") )
oDaniel:addInformacao( "DEV" )
oDaniel:addInformacao( "Cerveja" )

oRafael := DnlPessoa():New()

oRafael:setNome("Rafael")
oRafael:setSobrenome("Mendes")
oRafael:setNascimento( CtoD("03/09/2019") )
oRafael:addInformacao( "RN" )

oDaniel:addFilho(oRafael)

ConOut( oDaniel:toXml() )

oDaniel:destroy()

FreeObj(oDaniel)

return nil

Obs.: No exemplo eu apenas concatenei os array.

1 curtida

Obrigado, Daniel!

1 curtida

você pode usar a função abaixo:

Local cXML := ""

//--Levando em conta que você já tem o objeto xml representado por oXml a sintaxe abaixo converte ele em uma string //--através do XMLSTRING e grava na variável que é passada logo à frente, que é a cXML nesse exemplo.

SAVE oXML XMLSTRING cXML

//--Depois da linha acima o texto do xml estará gravado na variável cXML