Index: contrib/xml2/README.xml2 =================================================================== RCS file: /projects/cvsroot/pgsql/contrib/xml2/README.xml2,v retrieving revision 1.3 diff -c -r1.3 README.xml2 *** contrib/xml2/README.xml2 22 Jan 2005 22:14:14 -0000 1.3 --- contrib/xml2/README.xml2 22 Aug 2006 20:19:39 -0000 *************** *** 83,89 **** key - the name of the "key" field - this is just a field to be used as the first column of the output table i.e. it identifies the record from ! which each output row came. document - the name of the field containing the XML document --- 83,89 ---- key - the name of the "key" field - this is just a field to be used as the first column of the output table i.e. it identifies the record from ! which each output row came (see note below about multiple values). document - the name of the field containing the XML document *************** *** 150,155 **** --- 150,229 ---- as a more complicated example. Of course, you could wrap all of this in a view for convenience. + Multivalued results + + The xpath_table function assumes that the results of each XPath query + might be multi-valued, so the number of rows returned by the function + may not be the same as the number of input documents. The first row + returned contains the first result from each query, the second row the + second result from each query. If one of the queries has fewer values + than the others, NULLs will be returned instead. + + In some cases, a user will know that a given XPath query will return + only a single result (perhaps a unique document identifier) - if used + alongside an XPath query returning multiple results, the single-valued + result will appear only on the first row of the result. The solution + to this is to use the key field as part of a join against a simpler + XPath query. As an example: + + + CREATE TABLE test + ( + id int4 NOT NULL, + xml text, + CONSTRAINT pk PRIMARY KEY (id) + ) + WITHOUT OIDS; + + INSERT INTO test VALUES (1, ' + 123 + 112233 + '); + + INSERT INTO test VALUES (2, ' + 111222333 + 111222333 + '); + + + The query: + + SELECT * FROM xpath_table('id','xml','test', + '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c','1=1') + AS t(id int4, doc_num varchar(10), line_num varchar(10), val1 int4, + val2 int4, val3 int4) + WHERE id = 1 ORDER BY doc_num, line_num + + + Gives the result: + + id | doc_num | line_num | val1 | val2 | val3 + ----+---------+----------+------+------+------ + 1 | C1 | L1 | 1 | 2 | 3 + 1 | | L2 | 11 | 22 | 33 + + To get doc_num on every line, the solution is to use two invocations + of xpath_table and join the results: + + SELECT t.*,i.doc_num FROM + xpath_table('id','xml','test', + '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c','1=1') + AS t(id int4, line_num varchar(10), val1 int4, val2 int4, val3 int4), + xpath_table('id','xml','test','/doc/@num','1=1') + AS i(id int4, doc_num varchar(10)) + WHERE i.id=t.id AND i.id=1 + ORDER BY doc_num, line_num; + + which gives the desired result: + + id | line_num | val1 | val2 | val3 | doc_num + ----+----------+------+------+------+--------- + 1 | L1 | 1 | 2 | 3 | C1 + 1 | L2 | 11 | 22 | 33 | C1 + (2 rows) + + + XSLT functions --------------