@@ -83,7 +83,7 @@ xpath_table(key,document,relation,xpaths,criteria)
8383
8484key - the name of the "key" field - this is just a field to be used as
8585the first column of the output table i.e. it identifies the record from
86- which each output row came.
86+ which each output row came (see note below about multiple values) .
8787
8888document - the name of the field containing the XML document
8989
@@ -150,6 +150,80 @@ WHERE t.author_id = p.person_id;
150150as a more complicated example. Of course, you could wrap all
151151of this in a view for convenience.
152152
153+ Multivalued results
154+
155+ The xpath_table function assumes that the results of each XPath query
156+ might be multi-valued, so the number of rows returned by the function
157+ may not be the same as the number of input documents. The first row
158+ returned contains the first result from each query, the second row the
159+ second result from each query. If one of the queries has fewer values
160+ than the others, NULLs will be returned instead.
161+
162+ In some cases, a user will know that a given XPath query will return
163+ only a single result (perhaps a unique document identifier) - if used
164+ alongside an XPath query returning multiple results, the single-valued
165+ result will appear only on the first row of the result. The solution
166+ to this is to use the key field as part of a join against a simpler
167+ XPath query. As an example:
168+
169+
170+ CREATE TABLE test
171+ (
172+ id int4 NOT NULL,
173+ xml text,
174+ CONSTRAINT pk PRIMARY KEY (id)
175+ )
176+ WITHOUT OIDS;
177+
178+ INSERT INTO test VALUES (1, '<doc num="C1">
179+ <line num="L1"><a>1</a><b>2</b><c>3</c></line>
180+ <line num="L2"><a>11</a><b>22</b><c>33</c></line>
181+ </doc>');
182+
183+ INSERT INTO test VALUES (2, '<doc num="C2">
184+ <line num="L1"><a>111</a><b>222</b><c>333</c></line>
185+ <line num="L2"><a>111</a><b>222</b><c>333</c></line>
186+ </doc>');
187+
188+
189+ The query:
190+
191+ SELECT * FROM xpath_table('id','xml','test',
192+ '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c','1=1')
193+ AS t(id int4, doc_num varchar(10), line_num varchar(10), val1 int4,
194+ val2 int4, val3 int4)
195+ WHERE id = 1 ORDER BY doc_num, line_num
196+
197+
198+ Gives the result:
199+
200+ id | doc_num | line_num | val1 | val2 | val3
201+ ----+---------+----------+------+------+------
202+ 1 | C1 | L1 | 1 | 2 | 3
203+ 1 | | L2 | 11 | 22 | 33
204+
205+ To get doc_num on every line, the solution is to use two invocations
206+ of xpath_table and join the results:
207+
208+ SELECT t.*,i.doc_num FROM
209+ xpath_table('id','xml','test',
210+ '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c','1=1')
211+ AS t(id int4, line_num varchar(10), val1 int4, val2 int4, val3 int4),
212+ xpath_table('id','xml','test','/doc/@num','1=1')
213+ AS i(id int4, doc_num varchar(10))
214+ WHERE i.id=t.id AND i.id=1
215+ ORDER BY doc_num, line_num;
216+
217+ which gives the desired result:
218+
219+ id | line_num | val1 | val2 | val3 | doc_num
220+ ----+----------+------+------+------+---------
221+ 1 | L1 | 1 | 2 | 3 | C1
222+ 1 | L2 | 11 | 22 | 33 | C1
223+ (2 rows)
224+
225+
226+
153227XSLT functions
154228--------------
155229