【问题标题】:Extracting multi Row XML Data from POStGreSQL从 POSTGreSQL 中提取多行 XML 数据
【发布时间】:2017-02-11 02:22:57
【问题描述】:

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

似乎没有任何效果。

每个客户都有多个属性。

需要像这样导入到表中:

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';

【问题讨论】:

    标签: xml postgresql


    【解决方案1】:

    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),我不知道。

    【讨论】:

    • 感谢 Ashley,这是原始代码,但请注意 attributeUIDValue 不正确。不知何故需要获取 Attribute UIDValue 以匹配 xml 中实际出现的内容
    • 啊。首先,如果您有工作(但有错误)的代码,最好将其包括在内 - 它将问题从“我不知道从哪里开始”更改为“我有一个错误”,并且可以为我节省一个小时或两个查看不同的解决方案并进行测试。
    • 已更新以修复从属性树的其他分支中提取值的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    相关资源
    最近更新 更多