Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 XML в PL/SQL обрезает результат без предупреждения  [new]
MicXEm
Member

Откуда:
Сообщений: 5
Добрый день, господа!

Столкнулся с проблемой извлечения данных из xml с помощью pl/sql.
Проблема вот в чем: если тег имеет больше 65536 элементов-чаилдов, то извлечь у меня получается только N элементов-чаилдов, равное остатку от деления реального числа элементов-чаилдов на 65536. При этом никаких ошибок или предупреждений оракл не выдает.

В моем случае, некорректно отрабатывает следующий пример:

Имеется такой xml:

<?xml version="1.0" encoding="windows-1251" standalone="no" ?>
<SB DESCRIPTION="Классификатор предприятий.">
  <TABLES>
     <TBL NAME="SB_ORG_OBJ_PARAM_VALUES" CNT="74905">
        <R OBJ_ID="10840" OBJ_PRTP_ID="5" OBJ_PRTP_VALUES="NULL"></R>
        <R OBJ_ID="10021" OBJ_PRTP_ID="1" OBJ_PRTP_VALUES="СТАВРОПОЛЬСКИЙ КРАЙ"></R>
        <R OBJ_ID="10022" OBJ_PRTP_ID="6" OBJ_PRTP_VALUES="NULL"></R>
     
       ... > 64k строк

        <R OBJ_ID="10022" OBJ_PRTP_ID="7" OBJ_PRTP_VALUES="NULL"></R>
     </TBL>
  </TABLES> 
</SB>
Есть функция, которая CLOB преобзазует к оракловому датасету:

function GetOrgObjParamValuesTable(p_xml  clob) return PFO_UT_KL_OBJ_PARAM_VALUES_SET is
begin
   l_xml:=XMLTYPE.createXML(p_xml);
   select
     cast(multiset(
       select cast(extractvalue(value(t),'/R/@OBJ_ID') as NUMBER) OBJ_ID,  
              cast(extractvalue(value(t),'/R/@OBJ_PRTP_ID') as  NUMBER) OBJ_PRTP_ID,    
              utl_raw.cast_to_varchar2(extractvalue(value(t),'/R/@OBJ_PRTP_VALUES')) OBJ_PRTP_VALUES
       from table(xmlsequence(l_xml.extract('/SB/TABLES/TBL[@NAME="SB_ORG_OBJ_PARAM_VALUES"]/R'))) t) as PFO_UT_KL_OBJ_PARAM_VALUES_SET)
   into l_data from dual;

   return l_data;
end;
Замечу, что в xml-файле у меня 74905 элементов с тегом <R>.
Запускаем тестовый скрипт (xml-файл хранится в виде CLOB в таблице XX_CLOB):

declare 
 l_clob  clob;
 l_data PFO_UT_KL_OBJ_PARAM_VALUES_SET;
l_cnt    integer;
begin
 select clob_val into l_clob from XX_CLOB where id_clob=1;
 l_data:=GetOrgObjParamValuesTable(l_clob);
 select count(*) into l_cnt from table(l_data);
 DBMS_OUTPUT.put_line(l_cnt);
end;
скрипт возвращает результат = 9369 (если к 9369 прибавить 65536, получим то что требовалось - 74905)

Хорошо, пишу другой тестовый скрипт:

declare
  l_clob         clob; 
  l_doc          dbms_xmldom.DOMDocument;
  l_nlist         dbms_xmldom.DOMNodeList;
  l_xml          xmltype;  
  l_cnt          iteger;
begin

  select clob_val into l_clob from XX_CLOB where id_clob=1;

  l_xml:=xmltype.createxml(l_clob);
  l_doc := dbms_xmldom.newDOMDocument(l_xml);
  l_nlist:= dbms_xmldom.getElementsByTagName(l_doc,'R');
  l_cnt:= dbms_xmldom.getLength(l_nlist); 
  
  Dbms_Output.put_line(l_cnt);
end;
и этот скрипт возвращает результат = 9369

Поиски в инете и на металинке ничего полезного не дали.
Все вышесказанное относится к Oracle Database 10g Enterprise Edition Release 10.2.0.3.0.

Теперь, собственно, вопрос: Как вынуть все 74905 записей их этого xml используя pl/sql?
1 апр 08, 16:26    [5487969]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
Elic
Member

Откуда:
Сообщений: 29990
MicXEm
Поиски в инете и на металинке ничего полезного не дали.
Как насчёт схожего Bug 4377659 Schema validation with number of nodes > 64k results in LSX-201
1 апр 08, 16:45    [5488121]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
MicXEm
Member

Откуда:
Сообщений: 5
Согласен, проблема очень похожа на описаную мной, но в моем случае не выдается ошибок.
Все выглядит так, как будто все работает правильно.
1 апр 08, 17:12    [5488350]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
Zloxa
Member

Откуда: СССР ☭
Сообщений: 1033
я в шоке
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 
Connected as zloxa
 
declare
  l_clob         clob;
  l_par          dbms_xmlparser.Parser := dbms_xmlparser.newParser;
  l_doc          dbms_xmldom.DOMDocument;
  l_nlist        dbms_xmldom.DOMNodeList;
  l_xml          xmltype;
  l_cnt          integer;
  procedure write_lob(lob in out nocopy clob,val varchar2)
  is
  begin
    dbms_lob.writeappend(lob,length(val),val);
  end;
begin
  dbms_lob.createtemporary(l_clob,true);
  write_lob(l_clob,'<?xml version="1.0" encoding="windows-1251" standalone="no" ?>
<SB DESCRIPTION="Классификатор предприятий.">
  <TABLES>
     <TBL NAME="SB_ORG_OBJ_PARAM_VALUES" CNT="74905">');
  for i in 1 .. 74905 loop
    write_lob(l_clob,'
        <R OBJ_ID="'||to_char(10839+i)||'" OBJ_PRTP_ID="5" OBJ_PRTP_VALUES="NULL"></R>');
  end loop;
  write_lob(l_clob,'
     </TBL>
  </TABLES>
</SB>');
  dbms_xmlparser.parseClob(l_par,l_clob);
  l_doc := dbms_xmlparser.getDocument(l_par);
  l_nlist:= dbms_xmldom.getElementsByTagName(l_doc,'R');
  l_cnt:= dbms_xmldom.getLength(l_nlist);
  Dbms_Output.put_line('xmldom=>'||l_cnt);
  select count(*)
    into l_cnt
  from
  table(XMLSequence(extract(xmltype(l_clob),'SB/TABLES/TBL/R')));
  Dbms_Output.put_line('xmltype=>'||l_cnt);
end;
/
 
xmldom=>9369
xmltype=>9369
 
PL/SQL procedure successfully completed
1 апр 08, 17:35    [5488527]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
Zloxa
Member

Откуда: СССР ☭
Сообщений: 1033
Connected to Oracle9i Enterprise Edition Release 9.2.0.7.0 
.
.
.

xmldom=>9369
xmltype=>74905
 
PL/SQL procedure successfully completed
1 апр 08, 17:38    [5488561]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
Zloxa
Member

Откуда: СССР ☭
Сообщений: 1033
Явно гдето счетчик в разрядности переполняется :(

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 
.
.
  for i in 1 .. 65535 loop
.
.
/
 
xmldom=>65535
xmltype=>65535
 
PL/SQL procedure successfully completed

.
  for i in 1 .. 65536 loop
.
/
xmldom=>0
xmltype=>0
1 апр 08, 17:49    [5488667]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
MicXEm
Member

Откуда:
Сообщений: 5
Спасибо всем, вопрос закрыт.

Oracle® XML DB Developer's Guide 11g Release 1 (11.1)

"Large Node Handling Using DBMS_XMLDOM
Prior to Oracle Database 11g Release 1 (11.1), each text node or attribute value processed by Oracle XML DB was limited in size to 64 K bytes. Starting with release 11.1, this restriction no longer applies."


http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28369/xdb10pls.htm#sthref1114
1 апр 08, 18:38    [5488986]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
MicXEm
Member

Откуда:
Сообщений: 5
Хотя, нет, не закрыт. Я поспешил. Там другая проблема.
1 апр 08, 18:51    [5489059]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
Zloxa
Member

Откуда: СССР ☭
Сообщений: 1033
Коли тема заглоха, и других, более вразумительных ворк эраундов не предложено, смею предложить использовать Oracle XML Developer's Kit for PL/SQL идущего в стоставе "XDK 9i Production". Вычитав гдето на офф. сайте фразу " The Oracle XDK is a distinct Oracle product with its own version number.", рискнули поствить девятую версию XDK на 10g. Тщательно потесрировав те фишки, ради которых мы его ставили(XSL преобразования, проверка DTD), пришли к выводу, что он вполне работоспособен(в рамках наших требований) в отличии от XDBшных.
Ну и как бы побочный эффект:
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 
Connected as zloxa
 
declare
  l_clob         clob;
  l_par          dbms_xmlparser.Parser := dbms_xmlparser.newParser;
  l_doc          dbms_xmldom.DOMDocument;
  l_nlist        dbms_xmldom.DOMNodeList;
  x_par          xmlparser.Parser := xmlparser.newParser;
  x_doc          xmldom.DOMDocument;
  x_nlist        xmldom.DOMNodeList;
  l_cnt          integer;
  procedure write_lob(lob in out nocopy clob,val varchar2)
  is
  begin
    dbms_lob.writeappend(lob,length(val),val);
  end;
begin
  dbms_lob.createtemporary(l_clob,true);
  write_lob(l_clob,'<?xml version="1.0" encoding="windows-1251" standalone="no" ?>
<SB DESCRIPTION="Классификатор предприятий.">
  <TABLES>
     <TBL NAME="SB_ORG_OBJ_PARAM_VALUES" CNT="74905">');
  for i in 1 .. 74905 loop
    write_lob(l_clob,'
        <R OBJ_ID="'||to_char(10839+i)||'" OBJ_PRTP_ID="5" OBJ_PRTP_VALUES="NULL"></R>');
  end loop;
  write_lob(l_clob,'
     </TBL>
  </TABLES>
</SB>');
  dbms_xmlparser.parseClob(l_par,l_clob);
  l_doc := dbms_xmlparser.getDocument(l_par);
  l_nlist:= dbms_xmldom.getElementsByTagName(l_doc,'R');
  l_cnt:= dbms_xmldom.getLength(l_nlist);
  Dbms_Output.put_line('dbms_dom=>'||l_cnt);
  --
  xmlparser.parseClob(x_par,l_clob);
  x_doc := xmlparser.getDocument(x_par);
  x_nlist:= xmldom.getElementsByTagName(x_doc,'R');
  l_cnt:= xmldom.getLength(x_nlist);
  Dbms_Output.put_line('xdk_dom=>'||l_cnt);
end;
/
 
dbms_dom=>9369
xdk_dom=>74905
 
PL/SQL procedure successfully completed
4 апр 08, 11:46    [5503250]     Ответить | Цитировать Сообщить модератору
 Re: XML в PL/SQL обрезает результат без предупреждения  [new]
MicXEm
Member

Откуда:
Сообщений: 5
Поставили 4 апдейт пак и все заработало.

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0
.
.
.

xmldom=>74905
xmltype=>74905
 
PL/SQL procedure successfully completed

Вопрос закрыт. Всем спасибо.
4 апр 08, 13:52    [5504244]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить