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

Откуда:
Сообщений: 56
Добрый день всем! Копаюсь в просторах интернета и никак не могу найти нужный мне вариант обработки xml.
Суть такая - есть xml файл, в нем приблизительно такая структура:
<root> 
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>

  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
     </Item>
  </Card>

  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>

</root>


В одном из <Item> нет тега <Par3>. Как можно обнаружить такое место и добавить этот тэг?
13 дек 18, 17:09    [21763245]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
-2-
Member

Откуда:
Сообщений: 15330
Dr_Grizzly
добавить этот тэг
все равно, какое значение?
13 дек 18, 17:28    [21763279]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
Да, все равно
13 дек 18, 17:45    [21763293]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Dr_Grizzly
Да, все равно


+
with t as (
   select xmltype('
<root> 
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>

  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
     </Item>
  </Card>

  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>

</root>
'
) x
   from dual
)
select *
  from t
      ,xmltable('/root/*' passing t.x columns
                    a0 for ordinality
                   ,a1 varchar2(100) path '/Card/Item/Par1'
                   ,a2 varchar2(100) path '/Card/Item/Par2'
                   ,a3 varchar2(100) path '/Card/Item/Par3'
                );
13 дек 18, 17:57    [21763317]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
Спасибо, только не пойму что получается - матрица с тремя строками, в первой колонке содержание xml, во второй колонке последовательность 1-2-3 по строкам. а остальные две пустые...
13 дек 18, 18:24    [21763359]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
<XMLTYPE> 1 100355159 -1 2014-07-22T00:00:00 2014-07-24T00:00:00 11
<XMLTYPE> 2 100355159 -1 2014-07-25T00:00:00 2018-12-03T00:00:00 10
<XMLTYPE> 3 100355159 -1 2014-07-16T00:00:00 2014-07-21T00:00:00 10
<XMLTYPE> 4 100355159 -1 1970-01-01T00:00:00 2013-02-21T00:00:00 11
<XMLTYPE> 5 100355159 -1 2013-02-22T00:00:00 2014-07-15T00:00:00 10
<XMLTYPE> 6 100355159 -1 2018-12-04T00:00:00 9999-01-01T00:00:00


Немного ошибся я в коде когда преобразовывал. вообще вот что выдал запрос - в последней колонке в последней строке нет значения - как раз то место, где нет нужного тега. А теперь как его туда воткнуть можно? )
13 дек 18, 18:31    [21763369]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
Dr_Grizzly
Спасибо, только не пойму что получается - матрица с тремя строками, в первой колонке содержание xml, во второй колонке последовательность 1-2-3 по строкам. а остальные две пустые...

:)

with t as (select xmltype('<root> 
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
     </Item>
  </Card>
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>
</root>') f from dual
)-----------------------------
select XMLSerialize( document
                     xmlelement( "root"
                               , xmlagg(xmlelement( "Card"
                                                  , xmlelement( "Item"
                                                               , xmlelement("Par1", "Par1"), xmlelement("Par2", "Par2"), xmlelement("Par3", "Par3")
                                                               )
                               )))
                 --as varchar2(2000)
                 --as blob encoding 'utf-8'
                 indent size = 1
                 )
  from (
        select x.* 
          from t, xmltable('/root/Card/Item'
          passing f
          columns "Par1", "Par2", "Par3"
          ) x
       )  


Только не делайте так.
Если принципиально внутри oracle - то зарегистрируйте схему и воспользуйтесь XMLSerialize SHOW DEFAULTS, оно умеет.
13 дек 18, 19:02    [21763399]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10051
Dr_Grizzly
В одном из <Item> нет тега <Par3>. Как можно обнаружить такое место и добавить этот тэг?


Ну если знаем имена всех тегов под Item:

drop table tbl purge
/
create table tbl
as select xmltype('<root> 
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
     </Item>
  </Card>
  <Card>
     <Item>
       <Par1>123</Par1>
       <Par2>AAADDDD</Par2>
       <Par3>9999</Par3>
     </Item>
  </Card>
</root>') x from dual
/
with t as (
           select card_no,
                  xmlagg(
                         xmlelement(
                                    "Item",
                                    xmlelement("Par1",par1),
                                    xmlelement("Par2",par2),
                                    xmlelement("Par3",nvl(par3,'some value'))
                                   )
                        ) item
             from tbl,
                  xmltable(
                           '/root/Card'
                           passing x
                           columns
                             card_no for ordinality,
                             card xmltype path '/Card/Item'
                           ) x,
                  xmltable(
                           '/Item'
                           passing card
                           columns
                             item_no for ordinality,
                             par1 varchar2(10) path '/Item/Par1',
                             par2 varchar2(10) path '/Item/Par2',
                             par3 varchar2(10) path '/Item/Par3'
                           ) y
             group by card_no,
                      item_no
           )
select xmlserialize(
                    document
                    xmlelement(
                               "root",
                               xmlagg(
                                      xmlelement(
                                                 "Card",
                                                 xmlagg(
                                                        item
                                                       )
                                                )
                                     )
                              )
                    indent
                      size = 2
                   )
  from t
  group by card_no
/

XMLSERIALIZE(DOCUMENTXMLELEMENT("ROOT",XMLAGG(XMLELEMENT("CARD",XMLAGG(ITEM))))I
--------------------------------------------------------------------------------
<root>
  <Card>
    <Item>
      <Par1>123</Par1>
      <Par2>AAADDDD</Par2>
      <Par3>9999</Par3>
    </Item>
  </Card>
  <Card>
    <Item>
      <Par1>123</Par1>
      <Par2>AAADDDD</Par2>
      <Par3>some value</Par3>
    </Item>
  </Card>
  <Card>
    <Item>
      <Par1>123</Par1>
      <Par2>AAADDDD</Par2>
      <Par3>9999</Par3>
    </Item>
  </Card>
</root>


SQL> 


Но основой вопрос может ли Par3 быть NULL? Если да, то использование xmlelement("Par3",par3) в COLUMNS не отделаешься и придется проверять само наличие тега Par3.

SY.
13 дек 18, 19:07    [21763404]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18371
andrey_anonymous
зарегистрируйте схему и воспользуйтесь XMLSerialize SHOW DEFAULTS, оно умеет.

+
begin
  dbms_xmlschema.registerSchema(schemaURL => 'http://myschema'
  , schemaDoc => '<?xml version="1.0" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="root">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="Card" maxOccurs="unbounded">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Item" maxOccurs="unbounded">
                  <xs:complexType>
                    <xs:sequence>
                      <xs:element name="Par1" type="xs:string"/>
                      <xs:element name="Par2" type="xs:string"/>
                      <xs:element name="Par3" type="xs:string" default="DefaultValue"/>
                    </xs:sequence>
                  </xs:complexType>
                </xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
</xs:schema>'
  , local => true);
end;
/
PL/SQL procedure successfully completed


with t as (select xmltype('<root>
     <Card><Item><Par1>123</Par1><Par2>AAADDDD</Par2><Par3>9999</Par3></Item></Card>
     <Card><Item><Par1>123</Par1><Par2>AAADDDD</Par2>                 </Item></Card>
     <Card><Item><Par1>123</Par1><Par2>AAADDDD</Par2><Par3>9999</Par3></Item></Card>
     </root>'
,'http://myschema'
) f
from dual
)-----------------------------
select XMLSerialize( document f
                 as varchar2(2000)
                 --as blob encoding 'utf-8'
                 indent size = 1
                 show defaults
                 )
  from t
;
XMLSERIALIZE(DOCUMENTFASVARCHA
--------------------------------------------------------------------------------
<root>
 <Card>
  <Item>
   <Par1>123</Par1>
   <Par2>AAADDDD</Par2>
   <Par3>9999</Par3>
  </Item>
 </Card>
 <Card>
  <Item>
   <Par1>123</Par1>
   <Par2>AAADDDD</Par2>
   <Par3>DefaultValue</Par3>
  </Item>
 </Card>
 <Card>
  <Item>
   <Par1>123</Par1>
   <Par2>AAADDDD</Par2>
   <Par3>9999</Par3>
  </Item>
 </Card>
</root>

SQL> 
13 дек 18, 20:21    [21763444]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
Истина где-то рядом ))
Нашел еще одну штуку, но чуток не дотягиваю как поставить условие НЕ

with xmltab as
( select sys_nc_rowinfo$ as FXML from myxml t)

SELECT XMLQuery(
'copy $NEWXML := $XML modify (
for $i in $NEWXML/root/card/item
where exists($i/Par3) ---как сказать Не существует??? в таком виде работает для всех где есть ))
return insert node <Pa3>AASS</Par3> into $i
)
return $NEWXML'
passing FXML as "XML",
'TEST' as "NAME"
returning CONTENT
)
from xmltab
;
14 дек 18, 08:05    [21763620]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
Ура товарищи! Получилось! Спасибо вам за помощь!

Вот последний вариант
with xmltab as
( select sys_nc_rowinfo$ as FXML from myxml t)

SELECT XMLQuery(
'copy $NEWXML := $XML modify (
  for $i in $NEWXML/PACKAGE/POSTOBJECT/CD/SMCARDTAX
    where not(exists($i/TAXGROUPID))
     return insert node <name>thenname</name> into $i
 )
 return $NEWXML'
 passing FXML as "XML",
         'TEST' as "NAME"
 returning CONTENT
)
from xmltab
;
14 дек 18, 09:01    [21763648]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
-2-
Member

Откуда:
Сообщений: 15330
Dr_Grizzly
как поставить условие НЕ
Великая тайна, посмотреть в спецификации xquery функцию not, доступна не всем. Кстати, наличие значения само по себе логическое выражение, поэтому exists излишен. Ну и еще вариант - вообще не проверять существование, а брать "nvl".
Если структура xml известна целиком, то можно обойтись и без modify, обеспечив совместимость со старыми версиями БД:
<root><Card>{
for $x in /root/Card/Item
return <Item>{$x/Par1,$x/Par2,($x/Par3,element Par3{})[1]}</Item>
}</Card></root>

Закладываться на обязательное наличие пустого элемента плохой тон. Задавать в схеме nillable и потом в xml писать атрибут nil=true излишне громоздко. Переопределять всякие int как строку, чтобы вместить пустое значение тоже не самое удачное решение.
14 дек 18, 09:02    [21763650]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
-2-,

Хорошая мысль! Я ее покурю в перерыве. Спасибо!


Есть еще момент интересный ))
Сначала я хотел вставлять в недостающий тэг константное значение, но задачка немного усложнилась и теперь хочу туда втыкать параметр. Кручу xmlQuery по всякому, и прийти к результату не получается...
Возьмем уже работающий код и попробуем немного его подпилить
declare
v_taxgroup_val varchar2(10);
...
with xmltab as
            (select xmltype(v_clob) as FXML, v_taxgroup_val from dual)
          select XMLQuery('copy $NEWXML := $XML modify (
                            for $i in $NEWXML/PACKAGE/POSTOBJECT/CD/SMCARDTAX
                              where not(exists($i/TAXGROUPID))
                               return insert node <TAXGROUPID> $TAXGP </TAXGROUPID> into $i
                           )
                           return $NEWXML'
                           passing FXML as "XML",
                           v_taxgroup_val as "TAXGP",
                           'TEST' as "NAME"
                           returning CONTENT
                          )
            into v_xmltype
            from xmltab

такой вариант не прокатывает. Вставляет прям текстом "$TAXGP"...
Пробовал исключить из select и просто конкатенацию строк делать. не помогло

Явно где-то маленькая палочка в колесе застряла... Есть предложения как это можно победить?
19 дек 18, 14:27    [21768371]     Ответить | Цитировать Сообщить модератору
 Re: Вставка в XML недостающего тега  [new]
Dr_Grizzly
Member

Откуда:
Сообщений: 56
Победил задачку!

Вот результат:
with xmltab as
            (select xmltype(v_clob) as FXML from dual)
          select XMLQuery('copy $NEWXML := $XML modify (
                            for $i in $NEWXML/PACKAGE/POSTOBJECT/CD/SMCARDTAX
                              where not(exists($i/TAXGROUPID))
                               return insert node $TAG_TAX into $i
                           )
                           return $NEWXML'
                           passing FXML as "XML",                          
                           xmltype('<TAXGROUPID>'||v_taxgroup_val||'</TAXGROUPID>') as "TAG_TAX"
                           returning CONTENT
                          )
            into v_xmltype
            from xmltab;
19 дек 18, 15:03    [21768434]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить