Search code examples
sqlpostgresqlxpathpostgresql-10postgresql-11

PostgreSQL11 xpath query not working properly


When I execute below query in Postgres 10.12, it works properly.

SELECT (xpath('./sid/text()', c.node))[1]::text::bigint AS STUDENT_ID,
       (xpath('./name/text()', c.node))[1]::text AS STUDENT_NAME
from (    
  select unnest(xpath('/data', '<data><sid>112233</sid><name>John</name></data>'::xml)) AS node    
) c;

Output:

enter image description here

But When I execute same query in Postgres 11.7, it is not working.

enter image description here

What is the solution to fix this issue?


Solution

  • This is caused by this change:

    Correctly handle relative path expressions in xmltable(), xpath(), and other XML-handling functions (Markus Winand)

    Per the SQL standard, relative paths start from the document node of the XML input document, not the root node as these functions previously did.

    so you need to change it to:

    SELECT (xpath('/data/sid/text()', c.node))[1]::text::bigint AS STUDENT_ID,
           (xpath('/data/name/text()', c.node))[1]::text AS STUDENT_NAME
    from (    
      select unnest(xpath('/data', '<data><sid>112233</sid><name>John</name></data>'::xml)) AS node    
    ) c;
    

    because the inner xpath will return the <data> tag as well:

    select unnest(xpath('/data', '<data><sid>112233</sid><name>John</name></data>'::xml)) AS node
    

    results in:

    <data>
      <sid>112233</sid>
      <name>John</name>
    </data>
    

    However, I would use xmltable for this:

    select *
    from xmltable('/data'
                   passing xml('<data><sid>112233</sid><name>John</name></data>')
                   columns 
                      student_id bigint path 'sid', 
                      student_name text path 'name')