Такого вопроса про XML я не нашла (про CAST(MULTISET ())

vikki
Дата: 31.05.2006 23:57:40
Здравствуйте. Очень нужна помощь, все горит, надо было сделать вчера.
Мне требуется получть XML-файл следующей структуры:
<?xml version="1.0" encoding="WINDOWS-1251" ?>
 <REZIDENT>
  <NAME_REZ>ООО Мкран</NAME_REZ>
  <INN_REZ>20902</INN_REZ>
  <KPP_REZ>1001</KPP_REZ>
  <ADR_REZ>Алтайский край</ADR_REZ>
  <DATA_BB>23/05/2006</DATA_BB>
  <AKTS>
   <AKT REC="1">
    <N_AKT>10/0102</N_AKT>
    <DAT_AKT>01/01/2006</DAT_AKT>
    <KVALN>840</KVALN>
    <SUMN_15251>0</SUMN_15251>
    <SUMN_15252>0</SUMN_15252>
    <SUMN_15253>0</SUMN_15253>
    <SUMN_15254>0</SUMN_15254>    
    <KUND_PAYMENTS NREC="4">     
      <KUND_PAYMENT RECID="1">
       <N_PC>59/00</N_PC>
       <N_PLAT>0000000010</N_PLAT>
       <D_PLAT>26/07/2005</D_PLAT>
       <PRIM_T>AAA</PRIM_T>
      </KUND_PAYMENT>
        <KUND_PAYMENT RECID="2">
       ...
        </KUND_PAYMENT>    
      </KUND_PAYMENTS>
   </AKT>
   <AKT>
    ...
    </AKT>
  </AKTS>
 </REZIDENT>
Важно, чтобы в тег <KUND_PAYMENTS> записывался атрибут NREC, равный количеству повторений <KUND_PAYMENT> .
Я деляю через типы и CAST(MULTISET ), и у меня добавляется лишний тег <KUND_PAYM>
create type KUND_PAYMENT as object("@RECID"     number,
                                    N_PC    VARCHAR2(22),
                                    N_PLAT  VARCHAR2(10),
                                    D_PLAT  DATE,
                                    PRIM_T  VARCHAR2(50) );
/
create type KUND_PAYMENTS_LIST is table of KUND_PAYMENT;
/
create type KUND_PAYMS as object("@NREC"     number,
                                  KUND_PAYM KUND_PAYMENTS_LIST);                                                                        
/
create type AKT as object( "@REC"     number,
                           N_AKT      VARCHAR2(23),
                           DAT_AKT    DATE,
                           KVALN      VARCHAR2(3),
                           PR_NAR     VARCHAR2(1),
                           SUMN_15251 NUMBER(16,2),
                           SUMN_15252 NUMBER(16,2),
                           SUMN_15253 NUMBER(16,2),
                           SUMN_15254 NUMBER(16,2),                          
                           kund_payments  kund_payms);
/
create type AKT_LIST is table of AKT;
/

declare
 --n_pc_  varchar2(22);
  CURSOR Ved_cur IS SELECT NAME_REZ, OGRN_REZ, DAT_REG, INN_REZ, KPP_REZ, ADR_REZ, DATA_BB,
                           DDEL, DMODIFY, TMODIFY,PRIM_T, NGOT_INS, NGOT_DOP, KOD_RTU, KOD_TAM, 
                           KOD_POST, PR_U_T_P, NVFTS_U, DVFTS_U,rowid  FROM  rvk_rezident ; --where rownum<=5 ;
  ved_rec ved_cur%ROWTYPE;  
  result CLOB;
  qryCtx DBMS_XMLGEN.ctxHandle; 
  n_text varchar2(500);
  len number;   
  p1 number:=10; 
BEGIN
  n_text:= 'DDT';  
 OPEN ved_cur;
  LOOP
    FETCH ved_cur INTO ved_rec;
    EXIT WHEN ved_cur%NOTFOUND;  
      DBMS_XMLGEN.setRowTag(qryCtx, NULL);
      qryCtx := DBMS_XMLGEN.newContext
         ( 'select  NAME_REZ, OGRN_REZ, DAT_REG, INN_REZ, KPP_REZ, ADR_REZ, DATA_BB, DDEL, DMODIFY, TMODIFY,
                    PRIM_T, NGOT_INS, NGOT_DOP, KOD_RTU, KOD_TAM, KOD_POST, PR_U_T_P, NVFTS_U, DVFTS_U,
         CAST(MULTISET (select rownum,a.N_AKT,a.DAT_AKT,a.KVALN,a.PR_NAR,a.SUMN_15251,a.SUMN_15252,a.SUMN_15253,a.SUMN_15254,
                       KUND_PAYMS((select count(*) from rvk_delo_oplata ff 
                      where ff.inn_rez=x.inn_rez and ff.kpp_rez=x.kpp_rez  and ff.n8=a.n_akt),
            CAST(MULTISET (select rownum,f.N_PC, f.N_PLAT, f.D_PLAT, f.PRIM_T
                    from rvk_delo_oplata f 
                      where f.inn_rez=x.inn_rez and f.kpp_rez=x.kpp_rez  and f.n8=a.n_akt) as KUND_PAYMENTS_LIST)) as KUND_PAYMENTS
               from rvk_akt a where a.inn_rez=x.inn_rez and a.kpp_rez=x.kpp_rez) as AKT_LIST) as AKTS
              from rvk_rezident x  where rowid='||chr(39)||ved_rec.rowid||chr(39)) ; 
     result := DBMS_XMLGEN.getXML(qryCtx);
      DBMS_XMLGEN.closeContext(qryCtx);
      result:=replace(result,'<ROWSET>'||chr(10),'');
      result:=replace(result,'</ROWSET>'||chr(10),'');
      result:=replace(result,'<ROW>','<REZIDENT>');
      result:=replace(result,'</ROW>','</REZIDENT>');
      insert into rezident_rvk values(result);     
  END LOOP; 
  close ved_cur;    
  commit;
END;
/
Получается вот что:
<?xml version="1.0" encoding="WINDOWS-1251" ?>
 <REZIDENT>
  <NAME_REZ>ООО Мкран</NAME_REZ>
  <INN_REZ>20902</INN_REZ>
  <KPP_REZ>1001</KPP_REZ>
  <ADR_REZ>Алтайский край</ADR_REZ>
  <DATA_BB>23/05/2006</DATA_BB>
  <AKTS>
   <AKT REC="1">
    <N_AKT>10/0102</N_AKT>
    <DAT_AKT>01/01/2006</DAT_AKT>
    <KVALN>840</KVALN>
    <SUMN_15251>0</SUMN_15251>
    <SUMN_15252>0</SUMN_15252>
    <SUMN_15253>0</SUMN_15253>
    <SUMN_15254>0</SUMN_15254>    
    <KUND_PAYMENTS NREC="4">
    <KUND_PAYM>
   <KUND_PAYMENT RECID="1">
       <N_PC>59/00</N_PC>
       <N_PLAT>0000000010</N_PLAT>
       <D_PLAT>26/07/2005</D_PLAT>
      </KUND_PAYMENT>
      <KUND_PAYMENT RECID="2">
       <N_PC>59/00</N_PC>
       <N_PLAT>0000000020</N_PLAT>
       <D_PLAT>03/08/2005</D_PLAT>
      </KUND_PAYMENT>
      <KUND_PAYMENT RECID="3">
       <N_PC>59/00</N_PC>
       <N_PLAT>0000000030</N_PLAT>
       <D_PLAT>11/08/2005</D_PLAT>
      </KUND_PAYMENT>
      <KUND_PAYMENT RECID="4">
       <N_PC>59/00</N_PC>
       <N_PLAT>0000000040</N_PLAT>
       <D_PLAT>12/08/2005</D_PLAT>
       <PRIM_T>A</PRIM_T>
      </KUND_PAYMENT>
    </KUND_PAYM>
     </KUND_PAYMENTS>
   </AKT>
  </AKTS>
 </REZIDENT>
КАК ИЗБАВИТЬСЯ от <KUND_PAYM>???? Но хочется использовать CAST(MULTISET()), а не XMLElement() XMLForest()
Может быть, можно как-то автоматически подсчитать количество выбираемых записей в тип?
Elic
Дата: 01.06.2006 01:00:49
vikki
Очень нужна помощь, все горит, надо было сделать вчера.
RTFM
Подобные формулировки провоцируют на "подумать послезавтра"
Viewer
Дата: 01.06.2006 07:04:24
Elic
vikki
Очень нужна помощь, все горит, надо было сделать вчера.
RTFM
Подобные формулировки провоцируют на "подумать послезавтра"

точнее... на "подумать позавчера" :))
vikki
Дата: 01.06.2006 10:53:14
Ну, а если серьезно! Можно подумать сегодня и завтра.
Неужели никто не ответит?
Я так надеялась, нашла много полезного на форуме и решила обратиться со своей промлемой!!!!
AlexOI
Дата: 01.06.2006 11:00:51
Вы же делаете потом replace. Ну и уберите эти теги еще одним replace.
Andrew IF
Дата: 01.06.2006 11:03:04
vikki
Ну, а если серьезно! Можно подумать сегодня и завтра.
Неужели никто не ответит?
Я так надеялась, нашла много полезного на форуме и решила обратиться со своей промлемой!!!!


Если серьёзно, то вопрос излишне загромождён несущественными подробностями. Придумайте упрощенную модель.

Маленька табличка с тестовыми данными:

create table...

insert into...
insert into...
insert into...

Желаемый XML без лишних загромождающих тэгов.

Ваш способ решения для модели. И проблема, которую решить не получается.

PS. Не забывайте пользоваться [src].
PPS. Прочитайте статью по ссылке от Elic. Несмотря на шуточную форму это вполне полезные рекомендации.
Ловец Стрекоз
Дата: 01.06.2006 11:26:54
SET long 5000;
DROP VIEW dept_xmlview;
CREATE VIEW dept_xmlview
AS
   SELECT XMLELEMENT
             ("Department",
              xmlattributes (deptno AS "Deptno",
                             (SELECT COUNT (1)
                                FROM emp e
                               WHERE e.deptno = d.deptno) AS "EmpCount"
                            ),
              XMLELEMENT ("DeptInfo",
                          XMLFOREST (dname AS "DepartName", loc AS "Location")
                         ),
              (SELECT XMLAGG (XMLELEMENT ("Employee",
                                          xmlattributes (empno AS "Empid"),
                                          XMLFOREST (ename AS "EmpName",
                                                     job AS "Job",
                                                     sal AS "Salary"
                                                    )
                                         )
                             )
                 FROM emp e
                WHERE e.deptno = d.deptno)
             ) AS department
     FROM dept d;

SELECT *
  FROM dept_xmlview;



Попробуйте проанализировать этот код и сделать соответствующие выводы.
Используется XML/SQL как наиболее предсказуемый способ генерации XML.
vikki
Дата: 02.06.2006 16:36:18
Andrew IF
vikki
Ну, а если серьезно! Можно подумать сегодня и завтра.
Неужели никто не ответит?
Я так надеялась, нашла много полезного на форуме и решила обратиться со своей промлемой!!!!


Если серьёзно, то вопрос излишне загромождён несущественными подробностями. Придумайте упрощенную модель.

Маленька табличка с тестовыми данными:

create table...

insert into...
insert into...
insert into...

Желаемый XML без лишних загромождающих тэгов.

Ваш способ решения для модели. И проблема, которую решить не получается.

PS. Не забывайте пользоваться [src].
PPS. Прочитайте статью по ссылке от Elic. Несмотря на шуточную форму это вполне полезные рекомендации.


Не поняла про таблицы? Мне нужна именно такая структура файла. Плюс, там еще есть вложенность, я не всю структуру привела. Слишком много
REPLACE получается.
А использовать SELECT XMLELEMENT
("Department",
xmlattributes ... не получается, ORACLE 9.2.0.1 выдает end-of-communication-channel
vikki
Дата: 05.06.2006 01:08:55
Неужели нет ни у кого мыслей?
Я прочитала статью по ссылке Elic, больше не буду так "вопить" (первый раз мучаствую в форуме, простите, завсегдатаи!!!).
Могу еще раз описать проблему.
Надо сформировать трехуровневый XML, с указанием у тега группы в качестве атрибута количества последующих записей. Я использую DBMS_XMLGEN.getXML, создаю типы, но возникает лишний тег: группа заворичивается в 3 тега, а надо в два.
Спасибо.
Ловец Стрекоз
Дата: 05.06.2006 10:06:49
автор
А использовать SELECT XMLELEMENT
("Department",
xmlattributes ... не получается, ORACLE 9.2.0.1 выдает end-of-communication-channel



Версия 9.2.0.1 честно говоря богата на заскоки с XML, это раз.
В версии 9.2.0.7 (более раннюю не нашел) все ОК, это два.
Нужно использовать клиента поддерживающего XML (SQL Navigator 5.0 справляется) , это три.