解析xml以在postgresql中创建插入

时间:2017-02-26 16:49:23

标签: xml postgresql

我的任务是创建将分层数据从postres关系表转换为xml并返回的机制。虽然我没有太多麻烦将表数据转换为xml,但我仍然坚持将实际的xml转换为多个插入。随着postgres提供的文档,我无能为力(。任何帮助将不胜感激。

xml的示例(独立的Button元素和带子节点的Grid):

<BTN>
    806
    <BTN_WINDOW />
</BTN>
<GRID>
    217
    <GRID_COLUMNS>
        <GRDCOL visible="true" vl_order="0"
            description="some description">
            <vl_props>some info</vl_props>
            <vl_params>some info</vl_svc_params>
            226
        </GRDCOL>
        <GRDCOL visible="true" vl_order="1"
            title="some description">
            <vl_props>some info</vl_props>
            <vl_params_1>some info</vl_svc_params>
            218
        </GRDCOL>
        <GRDCOL visible="true" vl_order="2" title="some description">
            <vl_props>some info</vl_props>
            <vl_svc_params>some info</vl_svc_params>
            219
        </GRDCOL>
        <GRDCOL visible="true" vl_order="3"
            title="some description">
            <vl_props>some info</vl_props>
            <vl_params>some info</vl_svc_params>
            220
        </GRDCOL>
     </GRID_COLUMNS>
</GRID>

解析xml后,我将为id为806的按钮生成插入语句                      806                      

INSERT INTO TABLE (ID, PARENT_ID,POSITION_IN_PARENT) VALUES (806,NULL,NULL)

然后我将生成一系列GRID及其列(GRDCOL)的插入,

  <GRID>
    217
    <GRID_COLUMNS>
        <GRDCOL visible="true" vl_order="0"
            description="some description">
            <vl_props>some info</vl_props>
            <vl_params>some info</vl_svc_params>
            226
        </GRDCOL>
        <GRDCOL visible="true" vl_order="1"
            title="some description">
            <vl_props>some info</vl_props>
            <vl_params_1>some info</vl_svc_params>
            218
        </GRDCOL>
        <GRDCOL visible="true" vl_order="2" title="some description">
            <vl_props>some info</vl_props>
            <vl_svc_params>some info</vl_svc_params>
            219
        </GRDCOL>
        <GRDCOL visible="true" vl_order="3"
            title="some description">
            <vl_props>some info</vl_props>
            <vl_params>some info</vl_svc_params>
            220
        </GRDCOL>
     </GRID_COLUMNS>
</GRID>

INSERT INTO TABLE (ID, PARENT_ID,POSITION_IN_PARENT) 
VALUES (217,NULL,NULL) --grid itself
INSERT INTO TABLE (ID, PARENT_ID, POSITION_IN_PARENT) 
VALUES (226,217,GRID_COLUMNS)   
INSERT INTO TABLE (ID, PARENT_ID, POSITION_IN_PARENT) 
VALUES (218,217,GRID_COLUMNS)
INSERT INTO TABLE (ID, PARENT_ID, POSITION_IN_PARENT) 
VALUES (219,217,GRID_COLUMNS)
INSERT INTO TABLE (ID, PARENT_ID, POSITION_IN_PARENT) 
VALUES (220,217,GRID_COLUMNS)

我无法弄清楚如何遍历xml中的每个节点并仅使用Postgres生成插入。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

解析XML文档比生成更难。但这是有可能的。

您可以使用XPATH功能 - 这对于大型文档也足够快。

对于以下文档:

<?xml version="1.0" encoding="windows-1250"?>
<enprimeur>
        <vino>
            <id>1</id>
            <nazev>Alter Ego de Palmer</nazev>
            <vyrobce>63</vyrobce>
            <rocnik>2012</rocnik>
            <cena0375>0</cena0375>
            <cena1500>0</cena1500>
            <cena3000>0</cena3000>
            <cena6000>0</cena6000>
            <cena0750>1425</cena0750>
            <cenastart>1085</cenastart>
            <min0375>0</min0375>
            <min0750>0</min0750>
            <odrudy>51 % Merlot, 40 % Cabernet Sauvignon,9 % Petit Verdot</odrudy>
            <bestin>2017 - 2026</bestin>
            <klas>2</klas>
            <sklad0375>0</sklad0375>
            <sklad0750>0</sklad0750>
            <sklad1500>0</sklad1500>
            <sklad3000>0</sklad3000>
            <sklad6000>0</sklad6000>
            <alk>13,4 %</alk>
            <remark>Premiant oblasti Margaux Ch. Palmer tentokrát ve svých obou vínech tì.il z dokonale zralého Merlotu, kterého do svých smìsí naládova
            <rating>Robert Parker: /100
TOPVINO SCORE: 92-94/100
James Suckling: 92-93/100
Wine Spectator: 90-93/100</rating>
            <zalozeno></zalozeno>
            <rozloha></rozloha>
            <stari></stari>
            <puda></puda>
            <produkce></produkce>
            <zrani></zrani>
            <active>1</active>
            <stitky>
            <stitek>8</stitek>
            <stitek>1</stitek>
            </stitky>
        </vino>
        <vino>
  ...

您可以使用q查询:

select x[1]::int id, x[2] nazev, x[3] vyrobce,
       x[4]::int rocnik, x[5]::double precision cena0375,
       x[6]::double precision cena1500, x[7]::double precision cena3000,
       x[7]::double precision cena6000, x[8]::double precision cena0750,
       x[9]::double precision cenastart, x[10]::double precision min0375,
       x[11]::double precision min0750, x[12] alk, x[13] klas
  from (select xpath('/vino/id/text()|'
'/vino/nazev/text()|/vino/vyrobce/text()|/vino/rocnik/text()|'
'/vino/cena0375/text()|/vino/cena1500/text()|/vino/cena3000/text()|'
'/vino/cena6000/text()|/vino/cena0750/text()|/vino/cenastart/text()|'
'/vino/min0375/text()|/vino/min0750/text()|/vino/alk/text()|'
'/vino/klas/text()', v)::text[] x 
          from (select unnest(xpath('/enprimeur/vino', d)) from xmldata) g(v)) s;

答案 1 :(得分:0)

我遇到的解决方案非常简单。

首先,我们找出当前xml中有多少个孩子。

SELECT btrim(xpath('count(./*)',
                     p_input_xml,
                     ARRAY [ ARRAY [ 'el',
                     'http://example.com' ],
                     array [ 'p',
                     'http://example1.com' ] ]) ::text,
               '{}')
    into v_child_count;

然后我们遍历孩子,然后递归地找到孩子的孩子,依此类推。因此我们将xml切碎成更小的xml。

select replace(btrim(xpath(format('./*[%s]', CURRENT_CHILD_ID),
                               p_input_xml,
                               ARRAY [ ARRAY [ 'el',
                               'http://example.com' ] ]) ::text,
                         '"{}"'),
                   '\"',
                   '"') ::xml
      into v_child_xml;