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.