2016-10-03 129 views
-3

下面我有XML,我必須導入到POSTGresQL數據庫中。從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'; 

回答

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

+0

感謝阿什利,這是原始代碼,但請注意屬性UID值是不正確的。不知何故需要獲得Attribute UIDValue以匹配xml – user1602327

+0

Ahh中的實際內容。首先,如果你有工作(但是有問題)的代碼,最好把它包括進去 - 它將問題從「我不知道從哪裏開始」改爲「我有一個bug」,並且會爲我節省一個小時或者兩個在尋找不同的解決方案並進行測試。 – agittins

+0

已更新,以修復將從屬性樹的其他分支中提取值的問題。 – agittins