Skip to content
Advertisement

Filtering multiple XML nodes using XPath in PostgreSQL

There is an XML with the structure:

- Item
  - Documents
    - Document
      - Records
        - Record
          - Category
            - Code
          - Value

And here is the SQL query that selects record values filtered by category code

SELECT  (xpath('/ns:Record/ns:Value/text()', rec, ARRAY[ARRAY['ns', 'http://some-ns']]))[1]::text AS val
FROM    (
    SELECT  unnest(xpath('/ns:Item/ns:Documents/ns:Document/ns:Records/ns:Record[ns:Category/ns:Code/text()="MAIN.CAT001"]',
               '<Item xmlns="http://some-ns"><Documents><Document><Records><Record><Category><Code>MAIN.CAT001</Code></Category><Value>Value 001</Value></Record><Record><Category><Code>MAIN.CAT002</Code></Category><Value>Value 002</Value></Record><Record><Category><Code>MAIN.CAT003</Code></Category><Value>Value 003</Value></Record></Records></Document></Documents></Item>'::xml,
               ARRAY[ARRAY['ns', 'http://some-ns']])) AS rec
) t

Is it possible to filter “records” not only by one “category code”, but by multiple ones? I mean I’d like to use filter like this

ns:Record[ns:Category/ns:Code/text()=("MAIN.CAT001", "MAIN.CAT003")]

or this

ns:Record[ns:Category/ns:Code/text()="MAIN.CAT001" or ns:Category/ns:Code/text()="MAIN.CAT003"]

But both solution don’t work

Advertisement

Answer

Try using contains(ns:Code,"MAIN.CAT001") or contains(ns:Code,"MAIN.CAT003")]:

SELECT  (xpath('/ns:Record/ns:Value/text()', rec, ARRAY[ARRAY['ns', 'http://some-ns']]))[1]::text AS val
FROM    (
  SELECT
    unnest(xpath('/ns:Item/ns:Documents/ns:Document/ns:Records/ns:Record[ns:Category[contains(ns:Code,"MAIN.CAT001") or contains(ns:Code,"MAIN.CAT003")]]',
                 '<Item xmlns="http://some-ns"><Documents><Document><Records><Record><Category><Code>MAIN.CAT001</Code></Category><Value>Value 001</Value></Record><Record><Category><Code>MAIN.CAT002</Code></Category><Value>Value 002</Value></Record><Record><Category><Code>MAIN.CAT003</Code></Category><Value>Value 003</Value></Record></Records></Document></Documents></Item>'::xml,
                 ARRAY[ARRAY['ns', 'http://some-ns']])) AS rec
) t;

    val    
-----------
 Value 001
 Value 003
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement