Gebruik de xpath()
functie:
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()
stript de omringende <status>
tag.
Retourneert een array van xml
- met een enkel element in dit geval:
status
xml[]
-------
{ERROR_MISSING_DATA}
Toegepast op uw tafel
Als antwoord op uw vraagupdate kan dit eenvoudig zijn:
SELECT id, xpath('./status/text()', response::xml) AS status
FROM tbl;
Als u zeker weet dat er slechts één statustag per rij is, kunt u eenvoudig het eerste item uit de array extraheren:
SELECT id, (xpath('./status/text()', response::xml))[1] AS status
FROM tbl;
Als er meerdere statusitems kunnen zijn:
SELECT id, unnest(xpath('./status/text()', response::xml)) AS status
FROM tbl;
Krijgt u 1-n rijen per id
.
Cast naar xml
Aangezien u uw kolommen heeft gedefinieerd als van het type text
(in plaats van xml
, je nodig casten naar xml
uitdrukkelijk. De functie xpath()
verwacht de 2e parameters van het type xml
. Een tekenreeksconstante zonder type wordt gedwongen tot xml
automatisch, maar een text
kolom is niet. Je moet expliciet casten.
Dit werkt zonder expliciete cast:
SELECT xpath('./status/text()'
,'<?xml version="1.0" ?><response><status>SUCCESS</status></response>')
Een CTE zoals in mijn eerste voorbeeld behoeften een type voor elke kolom in de "common table expression". Als ik niet naar een specifiek type had gecast, het type unknown
zou zijn gebruikt - wat niet . is hetzelfde als een niet-getypte string . Het is duidelijk dat er geen directe conversie is geïmplementeerd tussen unknown
en xml
. Je zou moeten casten naar text
eerst:unknown_type_col::text::xml
. Beter casten naar ::xml
meteen.
Dit is aangescherpt met PostgreSQL 9.1 (denk ik). Oudere versies waren toleranter.
Hoe dan ook, met elk van deze methoden moet de string valid xml zijn of de cast (impliciet of expliciet) zal een uitzondering maken.