2015-05-29 4 views
9

У меня есть следующий фрагмент XML:Использование XMLTABLE и XQuery для извлечения данных из 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; 

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

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

Edit:

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

  • В документации также отмечается: «Для каждого результирующего столбца, кроме столбца FOR ORDINALITY, вы должны указать тип данных столбца», однако, как представляется, он работает без него. Также кажется немного лишним указать его для столбцов и для переменных, в которые я вставляю данные. Любая идея, если не указывать типы данных, может вызвать у меня проблемы?

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;        

ответ

1

По первому вопросу the documentation you linked имеет это день о опуская PATH:

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

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

(... COLUMNS xyz)

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

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

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

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


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

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

1

Ссылки:

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

How to parse xml by xmltable when using namespace in 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 без информации о пространстве имен.