Search code examples
xmloraclexpathplsqlxmltable

PLSQL XMLTable XPath get all tags of furthest depth


In PL/SQL is there a way to get all nodes of the furthest depth?

Example 1:

<responseObject>
    <response>
        <value1>A</value1>
        <value2>B</value2>
        <error>A11</error>
    <response>
<responseObject>

Example 2:

<responseObject>
    <response1>A</response1>
    <response2>B</response2>
    <response4>D</response4>
    <random>1</random>
<responseObject>

In example 1 I would like to get value1, value2, and error. In example 2 I would like to get response1, response2, response4, and random. Currently my XPath is set up as '/responseObject/*/*' but that doesn't work for the second case.

Sample Code:

DECLARE
  lxml xmltype;
begin
  lxml := 
  xmltype('<responseObject>
              <response>
                  <value1>A</value1>
                  <value2>B</value2>
                  <error>A11</error>
              <response>
           <responseObject>');

  FOR test IN (
    select tag,
           VALUE
    FROM   xmltable('responseObject/*/*'
             passing lxml
             columns
               tag VARCHAR2(128) path 'name()',
               VALUE VARCHAR2(128) path '.'
           ) t
  )
  LOOP
    dbms_output.put_line(test.tag || ' - ' || test.value);
  END LOOP;
end;

Solution

  • SQL Fiddle

    Oracle 11g R2 Schema Setup:

    CREATE TABLE table_name ( id, xml ) AS
    SELECT 1, '<responseObject>
        <response>
            <value1>A</value1>
            <value2>B</value2>
            <error>A11</error>
        </response>
    </responseObject>' FROM DUAL UNION ALL
    SELECT 2, '<responseObject>
        <response1>A</response1>
        <response2>B</response2>
        <response4>D</response4>
        <random>1</random>
    </responseObject>' FROM DUAL;
    

    Query 1:

    SELECT id, x.*
    FROM   TABLE_NAME t
           CROSS JOIN
           xmltable(
             '/responseObject//*[last()][not(*)]'
             passing XMLType( t.xml )
             COLUMNS
               tag   VARCHAR2(128) path 'name()',
               value VARCHAR2(128) path '.'
           ) x
    

    Results:

    | ID |    TAG | VALUE |
    |----|--------|-------|
    |  1 |  error |   A11 |
    |  2 | random |     1 |