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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby personid) as c on c.personid = p.id
;
and then format and clean up the resulting XML document with an XMLFormatter.
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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby 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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby 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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby 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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby 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,
droptableifexists wheel;droptableifexists car;droptableifexists person;createtable person
(
id integernotnull,
name charactervarying(30),
constraint person_pk primarykey (id)
);createtable car
(
id integernotnull,
type charactervarying(30),
personid integer,
constraint car_pk primarykey (id)
);createtable wheel
(
id integernotnull,
whichone charactervarying(30),
serialnumber integer,
carid integer,
constraint"wheel_pk"primarykey (id)
);insertinto person(id, name) values
(1, 'Johny'),
(2, 'Freddy'),
(3, 'Billy');insertinto car(id, type, personid) values
(1, 'Toyota', 1),
(2, 'Fiat', 2);insertinto wheel(id, whichone, serialnumber, carid) values
(1, 'front', '11', 1),
(2, 'back', '12', 1),
(3, 'front', '21', 2),
(4, 'back', '22', 2),
(5, 'front', '3', 3);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),
casewhen c.cars isnotnullthen c.cars
else xmlelement(name cars)
end
)
)
) _xml_output
from person as p
leftouterjoin (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
leftouterjoin (select
carid,
xmlelement(name wheels,
xmlagg(
xmlelement(name wheel, xmlattributes(id as wheelid),
xmlforest(whichone, serialnumber)
)
)
) as wheels
from wheel groupby carid) as y on y.carid = x.id
groupby 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 updatein my first post]
We use 3 different kinds of cookies. You can choose which cookies you want to accept. We need basic cookies to make this site work, therefore these are the minimum you can select. Learn more about our cookies.