:: Не фоксом единым
И ещё Oracle + XML
S-type

Сообщений: 2969
Дата регистрации: 24.04.2004
Есть XML:

<?xml version="1.0" encoding="windows-1251"?>
<response>
<data>
<Документ ВерсФорм="4.02" ИдДок="5CFC2923-A98D-E19A-E053-0200640AB0D8" ИдЗапросФ="355847376">
<КодОбр>52</КодОбр>
</Документ>
</data>
[...]

Мне нужно значение КодОбр. Извлекаю его:

l_xresponse.extract('//response/data/Документ/КодОбр/text()').getStringVal();

Дошёл в цикле до документа, в котором:

<?xml version="1.0" encoding="windows-1251"?>
<response>
<data>
<Документ ВерсФорм="4.02" ИдДок="5CFC2923-A98D-E19A-E053-0200640AB0D8" ИдЗапросФ="355847376" КодОбр="51"/>
</data>
[...]

Как можно вытащить КодОбр?

И ещё вопрос. Приходится extract оборачивать в begin + exception, что неудобно. Можно извлекать так, что бы возвращалось пусто, без перехвата исключения?
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
S-type

Сообщений: 2969
Дата регистрации: 24.04.2004
Вытащить КодОбр можно так:

extract('//response//data//Документ/@КодОбр')
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Что-то типа
(//Документ/КодОбр/text()|//Документ/@КодОбр)[1]
Объединяет оба результата поиска и потом выбирает первый из них.
Писать полный путь по иерархии не обязательно - разве что у тебя там на разных уровнях в разных ветках этот "Документ" живёт, и нужна именно ветка по указанному пути.
Если не хочешь обрабатывать ошибки, то проверяй то что шаг .extract() вернул не NULL (хоть что-то нашёл) прежде чем у возвращённого объекта метод getStringVal() дёргать.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
S-type

Сообщений: 2969
Дата регистрации: 24.04.2004
Спасибо.
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
ВладимирС
Автор

Сообщений: 1693
Дата регистрации: 03.11.2005
Что-то у меня не получается парсить XML. Может великие гуру помогут.
И так, имею XML, понятно взял попроще:

Хочу получить результат в виде таблицы:
claim_CODE | applications_CODE | constructions_CODE
...................................................
   413              877                1666
   413              877                1668
   413              877                1667
   413              878                1688
   413              879                1690
   413              879                1689
   413              880                1691
   413              881                1692
   413              882                1694
   413              882                1693
   413              883                1695

Получаю результат:
claim_CODE | applications_CODE
..............................
    413            877
    413            878
    413            879
    413            880
    413            881
    413            882
    413            883

А как написать запрос на желаемый результат ?
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
ВладимирС
Автор

Сообщений: 1693
Дата регистрации: 03.11.2005
Можно теги получить:
запрос типа:
WITH t as
(
SELECT xmltype('
<claim>
<code>413</code>
<applications>
<code>877</code>
<constructions>
<code>1666</code>
</constructions>
<constructions>
<code>1668</code>
</constructions>
<constructions>
<code>1667</code>
</constructions>
</applications>
<applications>
<code>878</code>
<constructions>
<code>1688</code>
</constructions>
</applications>
<applications>
<code>879</code>
<constructions>
<code>1690</code>
</constructions>
<constructions>
<code>1689</code>
</constructions>
</applications>
<applications>
<code>880</code>
<constructions>
<code>1691</code>
</constructions>
</applications>
<applications>
<code>881</code>
<constructions>
<code>1692</code>
</constructions>
</applications>
<applications>
<code>882</code>
<constructions>
<code>1694</code>
</constructions>
<constructions>
<code>1693</code>
</constructions>
</applications>
<applications>
<code>883</code>
<constructions>
<code>1695</code>
</constructions>
</applications>
</claim>') x FROM DUAL
)
SELECT
t1.extract('claim/code/text()').getStringVal() as claim_CODE
,t2.extract('applications/code/text()').getStringVal() as applications_CODE
,t2.extract('applications/constructions/code') as constructions_CODE
FROM t
,table(XMLSequence(EXTRACT(t.x,'claim'))) t1
,table(XMLSequence(EXTRACT(t.x,'claim/applications'))) t2

Результат:
claim_CODE | applications_CODE | constructions_CODE
...................................................
   413             877           <code>1666</code><code>1668</code><code>1667</code>
   413             878           <code>1688</code>
   413             879           <code>1690</code><code>1689</code>
   413             880           <code>1691</code>
   413             881           <code>1692</code>
   413             882           <code>1694</code><code>1693</code>
   413             883           <code>1695</code>
С дальнейшим парсить "constructions_CODE"...
Но XML на самом деле намного сложнее и такой подход конечно возможен, но как то непривлекателен.
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
....
SELECT CLAIM.EXTRACT('claim/code/text()').GETSTRINGVAL() CLAIM_CODE,
APPLICATION.EXTRACT('applications/code/text()').GETSTRINGVAL() APPLICATION_CODE,
CONSTRUCTION.EXTRACT('constructions/code/text()').GETSTRINGVAL() CONSTRUCTION_CODE
FROM T,
TABLE(XMLSEQUENCE(EXTRACT(T.X, 'claim'))) CLAIM,
TABLE(XMLSEQUENCE(CLAIM.EXTRACT('claim/applications'))) APPLICATION,
TABLE(XMLSEQUENCE(APPLICATION.EXTRACT('applications/constructions'))) CONSTRUCTION;

По идее следует переходить на использование XMLTable, нечто типа вот такого
....
SELECT CLAIM.CLAIM_CODE,
APPLICATION.APPLICATION_CODE,
CONSTRUCTION.CONSTRUCTION_CODE
FROM T
INNER JOIN
XMLTABLE('/claim' PASSING T.X
COLUMNS
CLAIM_CODE NUMBER PATH 'code',
APPLICATIONS XMLTYPE PATH 'applications') CLAIM ON 1 = 1
LEFT JOIN
XMLTABLE('/applications' PASSING CLAIM.APPLICATIONS
COLUMNS
APPLICATION_CODE NUMBER PATH 'code',
CONSTRUCTIONS XMLTYPE PATH 'constructions') APPLICATION ON 1 = 1
LEFT JOIN
XMLTABLE('/constructions' PASSING APPLICATION.CONSTRUCTIONS
COLUMNS
CONSTRUCTION_CODE NUMBER PATH 'code') CONSTRUCTION ON 1 = 1;
Но могут быть нюансы. Скажем по твоей структуре вместо LEFT JOIN с "тупым" условием связывания, т.к. все уровни заполнены (нет applications без constructions, ну и нет только claim/code без applications), можно было бы применить CROSS JOIN, или тот самый "старый" синтаксис с перечислением через запятую... Но скажем на версии 11.2.0.2/Win32 это стабильно валит серверный процесс в ORA-600 А на более свежей 12.1.0.2/Linux64 с некоторыми патчами уже работает как положено... Так что проверяй на своих версиях что будет работать стабильнее.
Есть ещё процедурный подход - используя пакет DBMS_XMLDOM, может оказаться более эффективным (а если "структура" XML-ей нестабильна/разнообразна/произвольна, то ещё и проще, т.к. не потребует "динамики" в SQL запросах использующих XML* функции).
P.S. Если XML документы предполагаются гигантские - по десяткам/сотням Мб - то стоит писать процедурный код разбора используя SAX парсер - но это уже чисто на Java (Java классы можно "встроить" в СУБД).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
ВладимирС
Автор

Сообщений: 1693
Дата регистрации: 03.11.2005
Igor Korolyov !
Супер, БОЛЬШОЕ ТЕБЕ СПАСИБО !
Как сам не догадался. Блин...
Второй запрос проанализирую...
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
keisov

Сообщений: 3
Дата регистрации: 25.01.2018
ВладимирС
Поздравляю)
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
ВладимирС
Автор

Сообщений: 1693
Дата регистрации: 03.11.2005
Не выходит что-то каменный цветок.
Чего-то недопонимаю.
Опять прошу помощи.

И так, будут присылаться XML файлы, которые нужно будет парсить, вытаскивать значения и загружать в таблицу.
Но, что-то попробовал на тестовой XML вытаскивать данные и не получается...
XMLTYPE принимает нормально.
Но только начинаем идти по тегам, результаты запроса выдаются пустыми.
SELECT ex.EXTRACT('export').GETSTRINGVAL() TEG_export
FROM T,
TABLE(XMLSEQUENCE(EXTRACT(T.X, 'export'))) ex

SELECT nsiOKPDList.EXTRACT('nsiOKPDList').GETSTRINGVAL() TEG_nsiOKPDList
FROM T,
TABLE(XMLSEQUENCE(EXTRACT(T.X, 'export'))) ex,
TABLE(XMLSEQUENCE(ex.EXTRACT('export/nsiOKPDList'))) nsiOKPDList

SELECT nsiOKPD.EXTRACT('nsiOKPD').GETSTRINGVAL() TEG_nsiOKPD
FROM T,
TABLE(XMLSEQUENCE(EXTRACT(T.X, 'export'))) ex,
TABLE(XMLSEQUENCE(ex.EXTRACT('export/nsiOKPDList'))) nsiOKPDList,
TABLE(XMLSEQUENCE(nsiOKPDList.EXTRACT('nsiOKPDList/nsiOKPD'))) nsiOKPD
И т.д....
Чувствую дело в Namespaces строки:
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://zakupki.gov.ru/oos/export/1" xmlnsos="http://zakupki.gov.ru/oos/types/1">
Но как это переработать, не знаю.
Как получить значения тегов всех <nsiOKPD> типа ?:
<oos:id>3321</oos:id>
<oos:parentId>3291</oos:parentId>
<oos:code>01.11.13</oos:code>
<oos:parentCode>01.11.1</oos:parentCode>
<oos:name>Кукуруза</oos:name>
<oos:comment>Эта группировка не включает: ....</oos:comment>
<oos:actual>true</oos:actual>



Исправлено 1 раз(а). Последнее : ВладимирС, 25.09.18 11:54
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
www.liberidu.com


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: И ещё Oracle + XML
ВладимирС
Автор

Сообщений: 1693
Дата регистрации: 03.11.2005
Igor Korolyov !
Большое спасибо!

Оставлю на память:
SELECT R.ID,R.PARENT_ID,R.CODE,R.PARENT_CODE,R.NAME,R.DESCRIPTION,
CASE WHEN actual = 'true' THEN 1
WHEN actual = 'false' THEN 0
ELSE Null
END IS_ACTUAL
FROM
(SELECT XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://zakupki.gov.ru/oos/export/1" xmlnsos="http://zakupki.gov.ru/oos/types/1">
<nsiOKPDList>
<nsiOKPD>
<oos:id>3284</oos:id>
<oos:code>Раздел A</oos:code>
<oos:name>ПРОДУКЦИЯ СЕЛЬСКОГО ХОЗЯЙСТВА, ОХОТЫ И ЛЕСНОГО ХОЗЯЙСТВА</oos:name>
<oos:actual>true</oos:actual>
</nsiOKPD>
<nsiOKPD>
<oos:id>3286</oos:id>
<oos:parentId>3284</oos:parentId>
<oos:code>Подраздел AА</oos:code>
<oos:parentCode>Раздел A</oos:parentCode>
<oos:name>ПРОДУКЦИЯ СЕЛЬСКОГО ХОЗЯЙСТВА, ОХОТЫ И ЛЕСНОГО ХОЗЯЙСТВА</oos:name>
<oos:actual>false</oos:actual>
</nsiOKPD>
<nsiOKPD>
<oos:id>3321</oos:id>
<oos:parentId>3291</oos:parentId>
<oos:code>01.11.13</oos:code>
<oos:parentCode>01.11.1</oos:parentCode>
<oos:name>Кукуруза</oos:name>
<oos:comment>Эта группировка не включает:
- кукурузу сахарную (см. 01.12.13.150)
- кукурузу кормовую (см. 01.11.60.170)</oos:comment>
<oos:actual>true</oos:actual>
</nsiOKPD>
</nsiOKPDList>
</export>') xml_data FROM DUAL
),
xmltable
(
xmlnamespaces(default 'http://zakupki.gov.ru/oos/export/1','http://zakupki.gov.ru/oos/types/1' as "oos"),
'/export/nsiOKPDList/nsiOKPD'
passing xml_data
columns
id number path 'oos:id',
parent_id number path 'oos:parentId',
code VARCHAR2(1000 CHAR) path 'oos:code',
parent_code VARCHAR2(1000 CHAR) path 'oos:parentCode',
name VARCHAR2(1000 CHAR) path 'oos:name',
description VARCHAR2(4000 CHAR) path 'oos:comment',
actual VARCHAR2(100 CHAR) path 'oos:actual'
) R;
Результат:

[attachment 30084 R.png]



Исправлено 1 раз(а). Последнее : ВладимирС, 27.09.18 07:04
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 3 (Гостей: 3)

© 2000-2024 Fox Club 
Яндекс.Метрика