【问题标题】:Using xpath to extract data from an XML column in postgres使用 xpath 从 postgres 中的 XML 列中提取数据
【发布时间】:2013-07-23 00:53:27
【问题描述】:

我做了下表:

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

【问题讨论】:

    标签: xml postgresql xpath xml-parsing


    【解决方案1】:

    这行得通:

    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"}
    

    注意我如何在third argument of xpath() 中为您的命名空间分配命名空间别名 n 并在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;
    

    &lt;rant&gt;是我自己还是大家都对json and jsonb感到高兴,所以我们不必处理XML。&lt;/rant&gt;

    【讨论】:

    • 很好的答案,在尝试使用涉及命名空间的 xpath 输出信息时为我工作!我同意解析 json 也可以容易得多。
    • 不只是你。但不是我……在所有情况下。有时 XML 更好:blogs.oracle.com/xmlorb/entry/analysis_of_json_use_cases
    • 阅读了 oracle 博客后,我更加确信 JSON 始终是最佳选择:-)。 jsonb 是 Postsgres 的一个很好的补充。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    相关资源
    最近更新 更多