It looks nice but now I would like to convert it to xml. I decided to use fme to query postgres just like in example and now I have noe idea how to convert the result to xml and write it to file.
Also talking about json which I also need (I need result in JSON and XML format) what I achieved is that I simply executed postgres query end then wrote results using simple text writer so I suppose that fme doesnt really know that the query result is a JSON :)
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
This post is closed to further activity.
It may be an old question, an answered question, an implemented idea, or a notification-only post.
Please check post dates before relying on any information in a question or answer.
For follow-up or related questions, please post a new question or idea.
If there is a genuine update to be made, please contact us and request that the post is reopened.
If you use the JSON reader it will recognize objects in the JSON as such and will make it easier to write it to XML.
Alternatively, you can use a SQLCreator to pass the query directly to your database and get the result back as FME features, that way you don't have to worry about the JSON part at all.
If you use the JSON reader it will recognize objects in the JSON as such and will make it easier to write it to XML.
Alternatively, you can use a SQLCreator to pass the query directly to your database and get the result back as FME features, that way you don't have to worry about the JSON part at all.
I updated my question so that it may be more clear what I actually need
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
Thanks for this great explanation. I completely focused on solution with fme json to xml conversion that I forgot about built in xml features in postgres.
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
Hi @witos, I would use the JSONFragmenter to fragment and flatten the JSON doc, and then use the XMLTemplater to construct an XML document.
JSON Attribute: persons
JSON Query: json["persons"][*]
Flatten Query Result into Attributes: Yes
Recursively Flatten Objects/Arrays : Yes
Here, you will have to design the destination XML schema and then set appropriate XML template expression(s) for the XMLtemplater. There is no way to generate XML schema (template) automatically from a JSON document unfortunately.
BTW, why not use the PostgreSQL XML functions? For example, execute this SQL script on an existing database with a SQLCreator,
drop table if exists wheel; drop table if exists car; drop table if exists person;
create table person ( id integer not null, name character varying(30), constraint person_pk primary key (id) ); create table car ( id integer not null, type character varying(30), personid integer, constraint car_pk primary key (id) ); create table wheel ( id integer not null, whichone character varying(30), serialnumber integer, carid integer, constraint "wheel_pk" primary key (id) );
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), xmlelement(name cars, (select xmlagg( xmlelement(name car, xmlattributes(c.id as carid), xmlelement(name type, c.type), xmlelement(name comment, 'nice car'), --constant xmlelement(name wheels, (select xmlagg( xmlelement(name wheel, xmlattributes(w.id as wheelid), xmlforest(whichone, serialnumber) ) ) from wheel as w where w.carid = c.id ) ) ) ) from car as c where c.personid = p.id ) ) ) ) ) as _xml_output from person as p;
[Update 2017-02-17: This SELECT statement could be more efficient than the above one]
select xmlelement(name persons, xmlagg( xmlelement(name person, xmlattributes(p.id as personid), xmlelement(name name, p.name), case when c.cars is not null then c.cars else xmlelement(name cars) end ) ) ) _xml_output from person as p left outer join (select x.personid, xmlelement(name cars, xmlagg( xmlelement(name car, xmlattributes(x.id as carid), xmlelement(name type, x.type), xmlelement(name comment, 'nice car'), y.wheels ) ) ) as cars from car as x left outer join (select carid, xmlelement(name wheels, xmlagg( xmlelement(name wheel, xmlattributes(id as wheelid), xmlforest(whichone, serialnumber) ) ) ) as wheels from wheel group by carid) as y on y.carid = x.id group by personid) as c on c.personid = p.id ;
and then format and clean up the resulting XML document with an XMLFormatter.
I tried to generate xml directly from sql query but it takes like 1k times longer then generating JSON. Did you know about this performance issue regarding xmlelement and xmlagg compared to json_build_object?
I don't know exact reason why the SQL query with XML functions took longer time than the query with JSON functions, but the SQL statement with XML functions has nested SELECT statement, so the number of sub query executions could be very large if the number of "person" records was large. I think it's one of possible reasons.
If so, this statement may be better than the previous one.
[Moved 2017-02-17: See the update in my first post]