Использование XMLTABLE и xquery для извлечения данных из xml

у меня есть следующий кусок XML:

<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
    xmlns:per="http://www.something.com/2014/11/bla/person">
    <per:Initials>E.C.</per:Initials>
    <per:FirstName>Erik</per:FirstName>
    <per:LastName>Flipsen</per:LastName>
    <per:BirthDate>1980-07-01</per:BirthDate>
    <per:Gender>Male</per:Gender>
</per:Person>

из этого xml я хочу извлечь некоторые данные в PL / SQL. Я хотел бы использовать XMLTABLE, так как функции EXTRACT и EXTRACTVALUE устарели.

Я могу извлечь данные, используя этот запрос:

select pers.Initials,
       pers.Firstname
    into lsInitials,
         lsFirstname
    from
    XMLTABLE ('*:Person' passing pxRequest
    columns Initials           PATH '*:Initials',
            Firstname          PATH '*:FirstName'
    )  pers;

Я использую подстановочные знаки для пространств имен, так как мне все равно, какие сокращения использует отправляющая сторона для пространства имен, я знаю точный путь, где получить мои данные в любом случае.

С этим кодом у меня есть две вещи, которые меня озадачивают:

  • согласно документации на http://docs.oracle.com/database/121/SQLRF/functions268.htm#SQLRF06232 путь должен быть необязательным, однако, как только я удаляю путь из раздела столбцов, я больше не получаю никаких результатов.

Edit:

я узнал, что когда я удаляю пространства имен для элементов и делаю их прописными буквами, это работает. Так похоже, что имена столбцов должны соответствовать именам элементов xml, чтобы заставить его работать. Я еще не понял, как заставить его работать с пространством имен XML.

  • в документации также отмечается "для каждого результирующего столбца, за исключением столбца для ординарности, вы должны указать тип данных столбца", однако, похоже, он отлично работает без него. Также кажется немного избыточным указывать его для столбцов и переменных, в которые я извлекаю данные. Любая идея, если не указать данные типы могут навлечь на меня неприятности?

Runnable образец кода:

SET SERVEROUTPUT ON;
DECLARE

    pxRequest xmltype := xmltype('<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd"
                                    xmlns:per="http://www.something.com/2014/11/bla/person">
                                    <per:Initials>E.C.</per:Initials>
                                    <per:FirstName>Erik</per:FirstName>
                                    <per:LastName>Flipsen</per:LastName>
                                    <per:BirthDate>1980-01-01</per:BirthDate>
                                    <per:Gender>Male</per:Gender>
                                </per:Person>');
    lsInitials  varchar2(100);
    lsFirstname varchar2(100);                                


begin

    select pers.Initials,
           pers.Firstname
        into lsInitials,
             lsFirstname
        from
        XMLTABLE ('*:Person' passing pxRequest
        columns Initials           PATH '*:Initials',
                Firstname          PATH '*:FirstName'
        )  pers;


    dbms_output.put_line(lsInitials);
    dbms_output.put_line(lsFirstname);

end;                            

2 ответов


согласно вашему первому вопросу,документация, которую вы связали имеет это на сегодняшний день о пропуске PATH:

необязательный элемент PATH предложение указывает, что часть результата XQuery, адресованная строкой выражения XQuery, должна использоваться в качестве содержимого столбца.

если вы опустите PATH, затем предполагается столбец выражения XQuery. Например:

(... COLUMNS xyz)

эквивалентно к

XMLTable(... COLUMNS xyz PATH 'XYZ')

вы можете использовать различные предложения PATH для разделения результата XQuery на разные столбцы виртуальной таблицы.

причина столбце xyz предполагается 'XYZ' потому что Oracle по умолчанию нечувствителен к регистру (по умолчанию-all-caps). Если бы вы определили свой столбец как "aBcD" тут PATH значение будет принято за 'aBcD'


что касается вашего второго вопроса об указании данных типы: если данные, которые вы извлекаете, всегда будут текстовыми, вы можете избежать указания типа данных.

однако, если вы начнете иметь дело с такими вещами, как даты, метки времени, числа с плавающей запятой и т. д., Вы можете столкнуться с проблемами. Вам либо нужно вручную преобразовать их, используя TO_* функции или вы можете указать их типы данных в Столбцах. Если вы этого не сделаете, Oracle может неявно использовать его, как считает нужным, что могут иметь неожиданные последствия.


ссылки:

https://stackoverflow.com/a/9976068/377141

как анализировать xml с помощью xmltable при использовании пространства имен в xml (Oracle)

он должен работать так, как ожидалось, если вы загружаете элементы пространства имен в xmltable:

select results    
from xmltable( 
  xmlnamespaces(
    default 'http://tempuri.org/',    
    'http://schemas.xmlsoap.org/soap/envelope/' as "soap" 
  ),    
  'soap:Envelope/soap:Body/addResponse' passing xmltype(v_xml) 
   columns results varchar(100) path './addResult')

из вашего примера (вам также может потребоваться зарегистрировать схему/пространство имен раньше времени, но это должно быть один раз):

select pers.Initials,
       pers.Firstname
    into lsInitials,
         lsFirstname
    from
    XMLTABLE (
      xmlnamespaces(
        default 'http://tempuri.org/',   
        'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
        'http://www.something.com/2014/11/bla/person' as "per" 
      ),
    passing pxRequest
    columns Initials           PATH '*:Initials',
            Firstname          PATH '*:FirstName'
    )  pers;

вещи, которые раньше работали в предыдущие версии Oracle не работают в 11g+ в отношении XML, так как из того, что я видел, Oracle сильно проверяет/вводит/вывод операций XML, где в предыдущих версиях вы могли бы запускать обычные правильные операции XQuery без информации о пространстве имен.