Larry
Larry

Reputation: 11949

Is there a good XML-to-Table that can be used in Java (or PostgreSQL)?

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

Answers (2)

Erwin Brandstetter
Erwin Brandstetter

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:

Test setup:

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);

Query:

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;

Result:

 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

hertzsprung
hertzsprung

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

Related Questions