Reputation: 11949
I’m looking for something exactly like: XMLTABLE, http://www.ibm.com/developerworks/data/library/techarticle/dm-0708nicola/
Does something like this exist in PostgreSQL, or what would be closest?
Or another way, is there a Java library that can accomplish this?
EDIT:
Thanks to Erwin (the answer in his comment is almost precisely what I was looking for).
However, perhaps I could suggest an extension to this.
Consider, we have an xml document like:
<comments photo_id=“123”>
</comment>this is the first comment</comment>
</comment>this is the second comment</comment>
</comments>
While, this is a simple example, consider also that “comment”
could be quite sophisticated.
My question is now: using the XMLTable function (or Erwin’s implementation), we need to specify a path_to_data
i.e. in this case (/comment
).
However, if I want my return schema to be something like: [photo_id, comment_text]
.
There is no way to get data from the elements of the parent of the datanum.
Is it therefore possible to somehow modify your code to do this? My guess is having something more sophisticated than the xpath function, which essentially returns a subset of data by tracing to the parent.
For example:
<comments photo_id=“123”>
</comment>this is the first comment</comment>
</comments>
<comments photo_id=“123”>
</comment>this is the second comment</comment>
</comments>
In this case, we can access “/comments/@photo_id”
.
Upvotes: 3
Views: 2648
Reputation: 658112
I finally got some time to take a closer look. From what I gather in your example this might be what you are looking for:
I added another node to make my point clear:
-- DROP TABLE t;
CREATE TEMP TABLE t (x xml);
INSERT INTO t VALUES (
'<tbl>
<comments photo_id="123">
<comment>this is the first 123 comment</comment>
<comment>this is the second 123 comment</comment>
</comments>
<comments photo_id="124">
<comment>this is the first 124 comment</comment>
<comment>this is the second 124 comment</comment>
<comment>this is the third 124 comment</comment>
</comments>
</tbl>'::xml);
SELECT (xpath('./@photo_id', c.node))[1] AS photo_id
, unnest(xpath('./comment/text()', c.node)) AS descriptor
FROM (
SELECT unnest(xpath('./comments', x)) AS node
FROM t
) c;
photo_id | descriptor
----------+--------------------------------
123 | this is the first 123 comment
123 | this is the second 123 comment
124 | this is the first 124 comment
124 | this is the second 124 comment
124 | this is the third 124 comment
The result looks very simple, but it caused me quite some headache to get there (a while ago, actually).
Key ingredients are the functions xpath() and unnest(). The trick is to do it in two steps. You can find some more explanation at this related answer.
Upvotes: 2
Reputation: 9903
PostgreSQL does have support for XML datatypes, but no direct support for XML-to-table conversion. You could write a XSLT stylesheet to convert your XML into SQL INSERT statements, or maybe look at a mapping tool such as Castor, which can convert between XML, Java beans and SQL.
Upvotes: 0