Ensuring that XMLTYPE to JSON transformations create JSON arrays - even when there is only a single element.
Recently, my colleagues and I were transforming a large quantity of XML to JSON via the APEX_JSON package. We wanted any XML tag that was repeated more than once to be transformed into a JSON array. However there was an issue with repeatable tags, whenever there was only one instance of the element then it wasn't created as an array.
Here's a very simplified example to illustrate the issue.
<parents>
<parent>
<name>Aidan</name>
<children>
<child>Aoife</child> <=== two entries
<child>Fionn</child>
</children>
</parent>
<parent>
<name>Eamon</name>
<children>
<child>Saoirse</child> <=== a single entry
</children>
</parent>
</parents>
[
{
"name":"Aidan",
"children":[ <=== this is what we want, an array.
"Aoife",
"Fionn"
]
},
{
"name":"Eamon",
"children":{ <=== we wanted an array here too :(
"child":"Saoirse"
}
}
]
set serveroutput on
declare
v_xml xmltype;
v_json clob;
begin
v_xml := xmltype(
'<parents>
<parent>
<name>Aidan</name>
<children>
<child>Aoife</child>
<child>Fionn</child>
</children>
</parent>
<parent>
<name>Eamon</name>
<children>
<child>Saoirse</child>
</children>
</parent>
</parents>');
apex_json.initialize_clob_output;
apex_json.write(v_xml);
v_json := apex_json.get_clob_output;
apex_json.free_output;
dbms_output.put_line(v_json);
end;
/
[
{"name":"Aidan",
"children":["Aoife","Fionn"]}, <=== is an array
{"name":"Eamon",
"children":{"child":"Saoirse"}} <=== is not an array :(
]
- if an XML node name is "rowset", then it always maps to an JSON array.
- if an XML node has a sub-node that ends in "_row", then it also always maps to an JSON array.
set serveroutput on
declare
v_xml xmltype;
v_json clob;
begin
v_xml := xmltype(
'<parents>
<parent>
<name>Aidan</name>
<children>
<child_row>Aoife</child_row>
<child_row>Fionn</child_row>
</children>
</parent>
<parent>
<name>Eamon</name>
<children>
<child_row>Saoirse</child_row>
</children>
</parent>
</parents>');
apex_json.initialize_clob_output;
apex_json.write(v_xml);
v_json := apex_json.get_clob_output;
apex_json.free_output;
dbms_output.put_line(v_json);
end;
/
[
{"name":"Aidan",
"children":["Aoife","Fionn"]}, <=== is an array
{"name":"Eamon",
"children":["Saoirse"]} <=== is also an array!!
]