从POStGreSQL中提取多行XML数据

时间:2016-10-03 07:35:06

标签: xml postgresql

下面我有XML我必须导入POSTGresQL数据库。

似乎没什么用。

每个客户都有多个属性。

需要导入到这样的表中:

create table CustomerAttXML (
    CustomerID varchar(30) NULL,
    AttributeUID varchar(30) NULL,
    AttributeName varchar(50) NULL,
    AttributeValue varchar(50) NULL,
    AttributeUIDValue varchar(50) NULL);

我几乎放弃了。

有没有人有任何想法?

<?xml version="1.0"?>
<Customers>
  <Customer>
    <customerId>C00100000</customerId>
    <title/>
    <firstName>Mary</firstName>
    <lastName>Kennedy</lastName>
    <dob/>
    <mobilePhone>Customer Declined</mobilePhone>
    <primaryEmail>Customer Declined</primaryEmail>
    <primaryAddress1>Customer Declined</primaryAddress1>
    <primaryAddress2>Customer Declined</primaryAddress2>
    <primaryCity>Customer Declined</primaryCity>
    <stateName>Customer Declined</stateName>
    <countryName>Customer Declined</countryName>
    <countryCode>36</countryCode>
    <primaryPostCode>3227</primaryPostCode>
    <homePhone>52222640</homePhone>
    <workPhone/>
    <subscribeToEmail>false</subscribeToEmail>
    <subscribeToSMS>true</subscribeToSMS>
    <Attributes>
      <Attribute>
        <attributeUid>13</attributeUid>
        <attributeValue>false</attributeValue>
        <attribDesc>Inactive Flag</attribDesc>
        <attributeUidValue/>
      </Attribute>
      <Attribute>
        <attributeUid>9</attributeUid>
        <attributeValue>false</attributeValue>
        <attribDesc>Flea &amp; Worming purchase</attribDesc>
        <attributeUidValue/>
      </Attribute>
      <Attribute>
        <attributeUid>7</attributeUid>
        <attributeValue>9308</attributeValue>
        <attribDesc>Store Code</attribDesc>
        <attributeUidValue>0001 Transylvania</attributeUidValue>
      </Attribute>
      <Attribute>
        <attributeUid>16</attributeUid>
        <attributeValue>SODOFF</attributeValue>
        <attribDesc>PasswordClearText</attribDesc>
        <attributeUidValue/>
      </Attribute>
    </Attributes>
  </Customer>
  <Customer>
    <customerId>C00121000</customerId>
    <title/>
    <firstName>Cherie</firstName>
    <lastName>Selby</lastName>
    <dob/>
    <mobilePhone>Customer Declined</mobilePhone>
    <primaryEmail>jCustomer Declinedm</primaryEmail>
    <primaryAddress1>Customer Declined</primaryAddress1>
    <primaryAddress2></primaryAddress2>
    <primaryCity>Customer Declinedl</primaryCity>
    <stateName>Customer Declined</stateName>
    <countryName>Customer Declined</countryName>
    <countryCode>36</countryCode>
    <primaryPostCode>Customer Declined</primaryPostCode>
    <homePhone>Customer Declined</homePhone>
    <workPhone/>
    <subscribeToEmail>true</subscribeToEmail>
    <subscribeToSMS>true</subscribeToSMS>
    <Attributes>
      <Attribute>
        <attributeUid>9</attributeUid>
        <attributeValue>false</attributeValue>
        <attribDesc>Flea &amp; Worming purchase</attribDesc>
        <attributeUidValue/>
      </Attribute>
      <Attribute>
        <attributeUid>13</attributeUid>
        <attributeValue>false</attributeValue>
        <attribDesc>Inactive Flag</attribDesc>
        <attributeUidValue/>
      </Attribute>
      <Attribute>
        <attributeUid>16</attributeUid>
        <attributeValue>Customer Declined</attributeValue>
        <attribDesc>PasswordClearText</attribDesc>
        <attributeUidValue/>
      </Attribute>
      <Attribute>
        <attributeUid>7</attributeUid>
        <attributeValue>Customer Declined</attributeValue>
        <attribDesc>Store Code</attribDesc>
        <attributeUidValue>Customer Declined</attributeUidValue>
      </Attribute>
    </Attributes>
  </Customer>
</Customers>

这是我目前无法解决的解决方案:

CREATE OR REPLACE FUNCTION public.import_custxmlattributes ( filename text )
RETURNS VOID AS
'
declare
    myxml xml;
    datafile text := $1;
    EachCustRecord RECORD;
    EachAttrRecord RECORD;

begin

drop table if exists byteb_v;

create temp table byteb_v AS
select bytea_import(datafile);

myxml := (select cast(encode(bytea_import,''escape'') as xml) from byteb_v) ;

drop table if exists CustomerAttXML;

create table CustomerAttXML (
    CustomerID varchar(30) NULL,
    AttributeUID varchar(30) NULL,
    AttributeName varchar(50) NULL,
    AttributeValue varchar(50) NULL,
    AttributeUIDValue varchar(50) NULL);

for EachCustRecord in
 select extract_value(''/Customer/customerId'', x) AS CustomerID,x as individual
 FROM unnest(xpath(''/Customers/Customer'', (select cast(encode(bytea_import,''escape'') as xml) from byteb_v))) x LOOP
  FOR EachAttrRecord IN
  SELECT xpath(''//Attributes/Attribute/attributeUid/text()'', EachCustRecord.individual ) AS AttributeUID,
         xpath(''//Attributes/Attribute/attribDesc/text()'', EachCustRecord.individual) AS AttributeName,
         xpath(''//Attributes/Attribute/attributeValue/text()'', EachCustRecord.individual) AS AttributeValue,
         xpath(''//Attributes/Attribute/attributeUidValue/text()'', EachCustRecord.individual) AS AttributeUIDValue
  FROM unnest(xpath(''/Customers/Customer'', (select cast(encode(bytea_import,''escape'') as xml) from byteb_v))) x LOOP
  RAISE NOTICE ''EachCustRecord.CustomerID(%)'', EachCustRecord.CustomerID;    
  RAISE NOTICE ''EachAttrRecord.AttributeUID(%)'', EachAttrRecord.AttributeUID;     
  RAISE NOTICE ''EachAttrRecord.AttributeName(%)'', EachAttrRecord.AttributeName;     
  RAISE NOTICE ''EachAttrRecord.AttributeValue(%)'', EachAttrRecord.AttributeValue;   
  RAISE NOTICE ''EachAttrRecord.AttributeUIDValue(%)'', EachAttrRecord.AttributeUIDValue;     
/*    insert into CustomerAttXML
    (CustomerID,AttributeUID,AttributeName,AttributeValue,AttributeUIDValue)
    values
    ( EachCustRecord.CustomerID, EachAttrRecord.AttributeUID, EachAttrRecord.AttributeName, EachAttrRecord.AttributeValue, EachAttrRecord.AttributeUIDValue ); */
  END LOOP;
END LOOP;
select pg_sleep(10);
end;'

LANGUAGE 'plpgsql';

1 个答案:

答案 0 :(得分:0)

Import XML files to PostgreSQL中汲取灵感,但在嵌套循环中完成,以避免从错误的分支中提取值...

CREATE or REPLACE function customerExtractFromXml() 
RETURNS TABLE (custid text, atuid text, atdesc text, atval text, atuval text) as $$
DECLARE
    thexml xml := ('<?xml version="1.0"?>
        <Customers>
          <Customer>
            <customerId>C00100000</customerId>
            <title/>
            <firstName>Mary</firstName>
            <lastName>Kennedy</lastName>
            <dob/>
            <mobilePhone>Customer Declined</mobilePhone>
            <primaryEmail>Customer Declined</primaryEmail>
            <primaryAddress1>Customer Declined</primaryAddress1>
            <primaryAddress2>Customer Declined</primaryAddress2>
            <primaryCity>Customer Declined</primaryCity>
            <stateName>Customer Declined</stateName>
            <countryName>Customer Declined</countryName>
            <countryCode>36</countryCode>
            <primaryPostCode>3227</primaryPostCode>
            <homePhone>52222640</homePhone>
            <workPhone/>
            <subscribeToEmail>false</subscribeToEmail>
            <subscribeToSMS>true</subscribeToSMS>
            <Attributes>
              <Attribute>
            <attributeUid>13</attributeUid>
            <attributeValue>false</attributeValue>
            <attribDesc>Inactive Flag</attribDesc>
            <attributeUidValue/>
              </Attribute>
              <Attribute>
            <attributeUid>9</attributeUid>
            <attributeValue>false</attributeValue>
            <attribDesc>Flea &amp; Worming purchase</attribDesc>
            <attributeUidValue/>
              </Attribute>
              <Attribute>
            <attributeUid>7</attributeUid>
            <attributeValue>9308</attributeValue>
            <attribDesc>Store Code</attribDesc>
            <attributeUidValue>0001 Transylvania</attributeUidValue>
              </Attribute>
              <Attribute>
            <attributeUid>16</attributeUid>
            <attributeValue>SODOFF</attributeValue>
            <attribDesc>PasswordClearText</attribDesc>
            <attributeUidValue/>
              </Attribute>
            </Attributes>
          </Customer>
          <Customer>
            <customerId>C00121000</customerId>
            <title/>
            <firstName>Cherie</firstName>
            <lastName>Selby</lastName>
            <dob/>
            <mobilePhone>Customer Declined</mobilePhone>
            <primaryEmail>jCustomer Declinedm</primaryEmail>
            <primaryAddress1>Customer Declined</primaryAddress1>
            <primaryAddress2></primaryAddress2>
            <primaryCity>Customer Declinedl</primaryCity>
            <stateName>Customer Declined</stateName>
            <countryName>Customer Declined</countryName>
            <countryCode>36</countryCode>
            <primaryPostCode>Customer Declined</primaryPostCode>
            <homePhone>Customer Declined</homePhone>
            <workPhone/>
            <subscribeToEmail>true</subscribeToEmail>
            <subscribeToSMS>true</subscribeToSMS>
            <Attributes>
              <Attribute>
            <attributeUid>9</attributeUid>
            <attributeValue>false</attributeValue>
            <attribDesc>Flea &amp; Worming purchase</attribDesc>
            <attributeUidValue/>
              </Attribute>
              <Attribute>
            <attributeUid>13</attributeUid>
            <attributeValue>false</attributeValue>
            <attribDesc>Inactive Flag</attribDesc>
            <attributeUidValue/>
              </Attribute>
              <Attribute>
            <attributeUid>16</attributeUid>
            <attributeValue>Customer Declined</attributeValue>
            <attribDesc>PasswordClearText</attribDesc>
            <attributeUidValue/>
              </Attribute>
              <Attribute>
            <attributeUid>7</attributeUid>
            <attributeValue>Customer Declined</attributeValue>
            <attribDesc>Store Code</attribDesc>
            <attributeUidValue>Customer Declined</attributeUidValue>
              </Attribute>
            </Attributes>
          </Customer>
        </Customers>
    ')::xml;
    customer text;
    attribute xml;
BEGIN


foreach customer in array xpath('//customerId/text()', thexml) LOOP
    foreach attribute in array xpath('//customerId[.='''||customer||''']/../Attributes/Attribute', thexml) LOOP
            custid := customer;
            atuid  := (xpath('attributeUid/text()', attribute))[1];
            atdesc := (xpath('attribDesc/text()', attribute))[1];
            atval  := (xpath('attributeValue/text()', attribute))[1];
            atuval := (xpath('attributeUidValue/text()', attribute))[1];
        return next ;
    END LOOP;
END LOOP;

END;
$$ LANGUAGE plpgsql;

select * from customerExtractFromXml();

运行此结果:

  custid   | atuid |           atdesc            |       atval       |      atuval       
-----------+-------+-----------------------------+-------------------+-------------------
 C00100000 | 13    | Inactive Flag               | false             | 
 C00100000 | 9     | Flea &amp; Worming purchase | false             | 
 C00100000 | 7     | Store Code                  | 9308              | 0001 Transylvania
 C00100000 | 16    | PasswordClearText           | SODOFF            | 
 C00121000 | 9     | Flea &amp; Worming purchase | false             | 
 C00121000 | 13    | Inactive Flag               | false             | 
 C00121000 | 16    | PasswordClearText           | Customer Declined | 
 C00121000 | 7     | Store Code                  | Customer Declined | Customer Declined
(8 rows)
缩小它将处理的XML部分是关键 - 可能有更有效的方法,可能只使用xpath(尽管可能仅使用xpath v2),我不知道。