Search code examples
pythonjsonxmlparsingxmltodict

Json to XML with attributes rather than elements


I need to parse an Json like:

{
"operacion": "ingresarOrdenBilateral",
"agente" : "0062",
"comitente" : 7211,
"fechaOrigen" : "2021-09-23T16:51:27.873-03:00",
"tipo" : "V",
"instrumento" : "GD30",
"tipoVenc" : "24",
"precio" : "100000000",
"cantidad" : "1",
"idOrigen" : 10699570
"ejecucion" : "SINCRONICA"
}

To this XML:

<ingresarOrdenBilateral 
agente="150" idOrigen="10039" fechaOrigen="2018-08-16T11:28:08.495-03:00" tipo="V" 
instrumento="AA17" tipoVenc="24" cantidad="1000000" precio="1625" formaOp="C" 
ejecucion="SINCRONICA"/> 

I have tried the library xmltodict and dicttoxml but I can't manage to get XML using attributes rather than elements. Also I think that the XML format is not standard.

Thanks!


Solution

  • Well, it can be done in one line using built-in xml.etree.ElementTree:

    import xml.etree.ElementTree as ET
    
    data = {
        "operacion": "ingresarOrdenBilateral",
        "agente": "0062",
        "comitente": 7211,
        "fechaOrigen": "2021-09-23T16:51:27.873-03:00",
        "tipo": "V",
        "instrumento": "GD30",
        "tipoVenc": "24",
        "precio": "100000000",
        "cantidad": "1",
        "idOrigen": 10699570,
        "ejecucion": "SINCRONICA"
    }
    ET.dump(ET.Element(data.pop("operacion"), {k: str(v) for k, v in data.items()}))
    

    Output:

    <ingresarOrdenBilateral agente="0062" comitente="7211" fechaOrigen="2021-09-23T16:51:27.873-03:00" tipo="V" instrumento="GD30" tipoVenc="24" precio="100000000" cantidad="1" idOrigen="10699570" ejecucion="SINCRONICA" />
    

    Upd. Assuming you're loading this JSON data either from file or server it's possible to pass str() to parse_int argument of json.load()/json.loads()/requests.Response.json(). It will force int fields to be parsed as str, so we can omit dict comprehension I've used in code above:

    import json
    import xml.etree.ElementTree as ET
    
    str_data = '''{
        "operacion": "ingresarOrdenBilateral",
        "agente": "0062",
        "comitente": 7211,
        "fechaOrigen": "2021-09-23T16:51:27.873-03:00",
        "tipo": "V",
        "instrumento": "GD30",
        "tipoVenc": "24",
        "precio": "100000000",
        "cantidad": "1",
        "idOrigen": 10699570,
        "ejecucion": "SINCRONICA"
    }'''
    data = json.loads(str_data, parse_int=str)
    ET.dump(ET.Element(data.pop("operacion"), data))
    

    There're also parse_float and parse_constant which you can use in same way (if needed, ofc).