在PostgreSQL中提取xml标记的值

时间:2013-04-15 19:43:20

标签: xml postgresql xpath casting xml-parsing

以下是我的Postgres表中的列响应。我想从Postgres数据库中的所有行中提取状态。状态可能有不同的大小,如SUCCESS,所以我不想使用子字符串函数。有办法吗?

<?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>

所以我的表结构就像这样

   Column    |            Type             |                        Modifiers                         

-------------+-----------------------------+----------------------------------------------------------

 id          | bigint                      | not null default nextval('events_id_seq'::regclass)
 hostname    | text                        | not null
 time        | timestamp without time zone | not null
 trn_type    | text                        | 
 db_ret_code | text                        | 
 request     | text                        | 
 response    | text                        | 
 wait_time   | text                        | 

我想从每个请求中提取状态。我该怎么做?

下面是一个示例行。并假设表名为abc_events

id          | 1870667
hostname    | abcd.local
time        | 2013-04-16 00:00:23.861
trn_type    | A
request     | <?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>
response    | <?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status><responseType>COUNTRY_MISSING</responseType><country_info>USA</country_info><phone_country_code>1234</phone_country_code></response>

1 个答案:

答案 0 :(得分:15)

使用xpath()功能:

WITH x(col) AS (SELECT '<?xml version="1.0" ?><response><status>ERROR_MISSING_DATA</status></response>'::xml)
SELECT xpath('./status/text()', col) AS status
FROM   x

/text()剥离了周围的<status>标记 返回一个xml数组 - 在这种情况下只包含一个元素:

status
xml[]
-------
{ERROR_MISSING_DATA}

应用于您的桌子

在回答您的问题更新时,这可能只是:

SELECT id, xpath('./status/text()', response::xml) AS status
FROM   tbl;

如果您确定每行只有一个状态标记,则只需从数组中提取第一个项目:

SELECT id, (xpath('./status/text()', response::xml))[1] AS status
FROM   tbl;

如果有多个状态项:

SELECT id, unnest(xpath('./status/text()', response::xml)) AS status
FROM   tbl;

id获取1行n。

转换为xml

由于您已将列定义为text类型(而不是xml,因此您需要明确地转换为xml。函数{{1期望xpath()类型的第二个参数。无类型的字符串常量会自动强制转换为xml,但 xml则不会。您需要​​强制转换明确。

这没有明确的演员:

text

CTE 就像在我的第一个例子中需要“公用表表达式”中每一列的类型。如果我没有转换为特定类型,则会使用类型 SELECT xpath('./status/text()' ,'<?xml version="1.0" ?><response><status>SUCCESS</status></response>') - 无类型字符串相同。显然,unknownunknown之间没有直接转换。您必须先转换为xmltext。最好立即投射到unknown_type_col::text::xml

PostgreSQL 9.1(我认为)已经收紧了。旧版本更宽松。

无论哪种方式,使用任何这些方法,字符串必须是有效的xml ,否则强制转换(隐式或显式)将引发异常。