Använd xpath()
funktion:
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() strippar den omgivande <status> tag.
Returnerar en array av xml - med ett enda element i detta fall:
status
xml[]
-------
{ERROR_MISSING_DATA}
Tillämpas på ditt bord
Som svar på din frågauppdatering kan detta helt enkelt vara:
SELECT id, xpath('./status/text()', response::xml) AS status
FROM tbl;
Om du är säker på att det bara finns en enda statustagg per rad kan du helt enkelt extrahera det första objektet från arrayen:
SELECT id, (xpath('./status/text()', response::xml))[1] AS status
FROM tbl;
Om det kan finnas flera statusobjekt:
SELECT id, unnest(xpath('./status/text()', response::xml)) AS status
FROM tbl;
Ger dig 1-n rader per id .
Casta till xml
Eftersom du definierade dina kolumner att vara av typen text (istället för xml
, du behöver för att casta till xml uttryckligen. Funktionen xpath() förväntar sig de andra parametrarna av typen xml . En otypad strängkonstant tvingas till xml automatiskt, men en text kolumn är inte. Du måste casta explicit.
Detta fungerar utan uttryckliga rollbesättningar:
SELECT xpath('./status/text()'
,'<?xml version="1.0" ?><response><status>SUCCESS</status></response>')
En CTE som i mitt första exempel på behov en typ för varje kolumn i "vanligt tabelluttryck". Om jag inte hade castat till en specifik typ, typen unknown skulle ha använts - vilket inte är samma sak som en oskriven sträng . Uppenbarligen finns det ingen direkt konvertering implementerad mellan unknown och xml . Du måste casta till text först:unknown_type_col::text::xml . Bättre att casta till ::xml direkt.
Detta har skärpts med PostgreSQL 9.1 (tror jag). Äldre versioner var mer tillåtande.
Hur som helst, med någon av dessa metoder måste strängen vara giltig xml eller så kommer skådespelaren (implicit eller explicit) att göra ett undantag.