Extracting value of xml tag in PostgreSQL

前端 未结 1 390
耶瑟儿~
耶瑟儿~ 2020-12-30 09:19

Below is the column response from my Postgres table. I want to extract the status from all the rows in my Postgres database. The status could be of varying sizes like

相关标签:
1条回答
  • 2020-12-30 09:35

    Use the xpath() function:

    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() strips the surrounding <status> tag.
    Returns an array of xml - with a single element in this case:

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

    Applied to your table

    In response to your question update, this can simply be:

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

    If you are certain there is only a single status tag per row, you can simply extract the first item from the array:

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

    If there can be multiple status items:

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

    Gets you 1-n rows per id.

    Cast to xml

    Since you defined your columns to be of type text (instead of xml, you need to cast to xml explicitly. The function xpath() expects the 2nd parameters of type xml. An untyped string constant is coerced to xml automatically, but a text column is not. You need to cast explicitly.

    This works without explicit cast:

      SELECT xpath('./status/text()'
          ,'<?xml version="1.0" ?><response><status>SUCCESS</status></response>')
    

    A CTE like in my first example needs a type for every column in the "common table expression". If I had not cast to a specific type, the type unknown would have been used - which is not the same thing as an untyped string. Obviously, there is no direct conversion implemented between unknown and xml. You'd have to cast to text first: unknown_type_col::text::xml. Better to cast to ::xml right away.

    This has been tightened with PostgreSQL 9.1 (I think). Older versions were more permissive.

    Either way, with any of these methods the string has to be valid xml or the cast (implicit or explicit) will raise an exception.

    0 讨论(0)
提交回复
热议问题