2013-07-23 21 views
3

我在下表製成提取數據:使用XPath從postgres的XML列

create table temp.promotions_xml(id serial promotion_xml xml); 

我已經插入以下數據temp.promotions:

<promotions xmlns="http://www.demandware.com/xml/impex/promotion/2008-01-31"> 
    <campaign campaign-id="2013-1st-semester-jet-giveaways"> 
     <description>2013 1st Semester Jet Giveaways</description> 
     <enabled-flag>true</enabled-flag> 
     <start-date>2013-01-01T05:00:00.000Z</start-date> 
     <end-date>2013-07-01T04:00:00.000Z</end-date> 
     <customer-groups> 
      <customer-group group-id="Everyone"/> 
     </customer-groups> 
    </campaign> 
</promotions> 

數據在桌子上。

我想不出如何把它弄出來。我可能會希望能夠填充我將構建的關係模型,所以我想擺脫所有標記。

以下是我試過的一些不起作用的問題。我很確定我只是圍繞正確的語法跳舞。這些查詢返回空集的行。

FWIW,我們使用的是Postgres 9.0.4。

感謝,--sw

select xpath('/promotions/campaign/description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('./promotions/campaign/description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('promotions/campaign/description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('///description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('//description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('.//description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('./campaign/description/text()',promotion_xml) textcol from temp.promotions_xml 
select xpath('//campaign/description/text()',promotion_xml) textcol from temp.promotions_xml 

回答

12

這工作:

WITH tbl(p_xml) AS ( -- CTE just to provide test table with xml value 
    SELECT '<promotions xmlns="http://www.demandware.com/xml/impex/promotion/2008-01-31"> 
       <campaign campaign-id="2013-1st-semester-jet-giveaways"> 
       <description>2013 1st Semester Jet Giveaways</description> 
       <enabled-flag>true</enabled-flag> 
       <start-date>2013-01-01T05:00:00.000Z</start-date> 
       <end-date>2013-07-01T04:00:00.000Z</end-date> 
       <customer-groups> 
        <customer-group group-id="Everyone"/> 
       </customer-groups> 
       </campaign> 
      </promotions>'::xml 
    ) -- end of CTE, the rest is the solution 
SELECT xpath('/n:promotions/n:campaign/n:description/text()', p_xml 
      , '{{n,http://www.demandware.com/xml/impex/promotion/2008-01-31}}') 
FROM tbl; 

返回:

{"2013 1st Semester Jet Giveaways"} 

注意我如何分配命名空間別名n在你的命名空間third argument of xpath()中,並在xpath的每個級別使用它。

如果您刪除文檔中的XML命名空間,一切都變得簡單多了:

WITH tbl(p_xml) AS ( -- not the missing namespace below 
    SELECT '<promotions> 
       <campaign campaign-id="2013-1st-semester-jet-giveaways"> 
       <description>2013 1st Semester Jet Giveaways</description> 
       <enabled-flag>true</enabled-flag> 
       <start-date>2013-01-01T05:00:00.000Z</start-date> 
       <end-date>2013-07-01T04:00:00.000Z</end-date> 
       <customer-groups> 
        <customer-group group-id="Everyone"/> 
       </customer-groups> 
       </campaign> 
      </promotions>'::xml 
    ) 
SELECT xpath('/promotions/campaign/description/text()', p_xml) 
FROM tbl; 

<rant>難道只是我還是大家都高興的事情json and jsonb,所以我們沒有處理XML。 </rant>

+1

很好的回答,在嘗試xpath out參與名稱空間的信息時爲我工作!我同意解析json也可以更容易。 – jhnclvr

+1

這不僅僅是你。但在所有情況下,這不是我......有時XML更好:https://blogs.oracle.com/xmlorb/entry/analysis_of_json_use_cases – btiernay

+1

閱讀了oracle博客後,我更加確信JSON始終是這樣的:-)。 jsonb是Postsgres的一個很好的補充。 –