从嵌套 XML PostgreSQL 中提取数据

Extracting data from nested XML PostgreSQL

我有一个 XML 需要插入 table。 XML 看起来像

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <pats>
      <pat>
         <id>1</id>
         <pat_maps>
            <pat_map>
               <pgid>100</pgid>
               <pgname>test</pgname>
            </pat_map>
            <pat_map>
               <pgid>101</pgid>
               <pgname>test1</pgname>
            </pat_map>
         </pat_maps>
      </pat>
      <pat>
         <id>2</id>
         <pat_maps>
            <pat_map>
               <pgid>102</pgid>
               <pgname>test2</pgname>
            </pat_map>
         </pat_maps>
      </pat>
      <pat>
         <id>3</id>
         <pat_maps>
            <pat_map>
               <pgid>104</pgid>
               <pgname>test6</pgname>
            </pat_map>
            <pat_map>
               <pgid>105</pgid>
               <pgname>test7</pgname>
            </pat_map>
         </pat_maps>
      </pat>
   </pats>
</root> 

我想按以下方式插入数据

ID  pgid    pgname
1   100     test
1   101     test1
2   102     test2
3   104     test6
3   105     test7

在下面尝试过,但它正在应用交叉连接

with x(t) as (select '<?xml version="1.0" encoding="UTF-8"?>
<root>
   <pats>
..............
..........
      </pat>
   </pats>
</root>'::xml AS t
)
, base_id as (SELECT 
    unnest(xpath('/root/pats/pat/id/text()', t)) AS id
from x
), nested_rec as ( select 
    unnest(xpath('pgid/text()', cat_assn_list)) AS pgid,
    unnest(xpath('pgname/text()', cat_assn_list)) AS pgname
from (select unnest(xpath('/root/pats/pat/pat_maps/pat_map', t)) cat_assn_list from x) q
) 
select base_id.*,nested_rec.* from base_id,nested_rec;

******* output *********
ID  PGID    PGNAME  
"1" "100"   "test"
"1" "101"   "test1"
"1" "102"   "test2"
"1" "104"   "test6"
"1" "105"   "test7"
"2" "100"   "test"
"2" "101"   "test1"
"2" "102"   "test2"
"2" "104"   "test6"
"2" "105"   "test7"
"3" "100"   "test"
"3" "101"   "test1"
"3" "102"   "test2"
"3" "104"   "test6"
"3" "105"   "test7"

我还没有找到方法,如何明智地嵌套 XML ID 并准备结果集?。 有没有其他方法可以在不使用 PostgreSQL 中的 XPath 函数的情况下将 xml 数据转换为 table? 提前致谢。

以下是您想要的,并且更短一些:

select (xpath('/pat/id/text()', d.pat))[1]::text::int as id,
       (xpath('/pat_map/pgid/text()', m.map))[1]::text::int as pgid,
       (xpath('/pat_map/pgname/text()', m.map))[1]::text as pgname
from x 
  cross join unnest(xpath('/root/pats/pat', x.t)) as d(pat)
  cross join unnest(xpath('/pat/pat_maps/pat_map', d.pat)) as m(map)
;

Online example

对于更现代的 Postgres 版本,您可以使用 xmltable():

select d.*
from x
  cross join xmltable ('/root/pats/pat/pat_maps/pat_map' 
                       passing t 
                       columns 
                        id integer path '../../id',
                        pgid integer path 'pgid', 
                        pgname text path 'pgname') as d