2013-11-12 4 views
1

Я новичок XPath; Я нашел способ сделать то, что хочу, но задаюсь вопросом, есть ли другой способ, который может сэкономить мне некоторое повторение в моем коде.Oracle XPath: Атрибут родительского узла?

У меня есть эта таблица:

CREATE TABLE t (
    quark_p1  VARCHAR2(4) 
, quark_p2  VARCHAR2(7) 
, quark_p3  VARCHAR2(6) 
, one    VARCHAR2(1) 
, two    VARCHAR2(1) 
, three   VARCHAR2(1) 
, four   VARCHAR2(1) 
, five   VARCHAR2(1) 
, six    VARCHAR2(1) 
, seven   VARCHAR2(1) 
, eight   VARCHAR2(1) 
, nine   VARCHAR2(1) 
) 
; 

Следующая PL/SQL анонимный блок делает то, что я хочу, извлекая в эту таблицу структуру из моего заданного XML:

BEGIN 
    INSERT INTO t (
     quark_p1 
    , quark_p2 
    , quark_p3 
    , one 
    , two 
    , three 
    , four 
    , five 
    , six 
    , seven 
    , eight 
    , nine 
    ) 
    SELECT x.quark_p1 
    ,  x.quark_p2 
    ,  x.quark_p3 
    ,  x.one 
    ,  x.two 
    ,  x.three 
    ,  x.four 
    ,  x.five 
    ,  x.six 
    ,  x.seven 
    ,  x.eight 
    ,  x.nine 
    FROM XMLTABLE('/BASIS/QUARK' 
    PASSING XMLTYPE (
     '<BASIS> 
      <QUARK P1="up" P2="charm" P3="bottom"> 
       <NEST> 
        <ONE>A</ONE> 
        <TWO>B</TWO> 
        <THREE>C</THREE> 
        <FOUR>D</FOUR> 
        <FIVE>E</FIVE> 
        <SIX>F</SIX> 
        <SEVEN>G</SEVEN> 
        <EIGHT>H</EIGHT> 
        <NINE>I</NINE> 
       </NEST> 
      </QUARK> 
      <QUARK P1="up" P2="strange" P3="top"> 
       <NEST> 
        <ONE>J</ONE> 
        <TWO>K</TWO> 
        <THREE>L</THREE> 
        <FOUR>M</FOUR> 
        <FIVE>N</FIVE> 
        <SIX>O</SIX> 
        <SEVEN>P</SEVEN> 
        <EIGHT>Q</EIGHT> 
        <NINE>R</NINE> 
       </NEST> 
      </QUARK> 
     </BASIS>') 
    COLUMNS quark_p1 VARCHAR2(4) PATH '@P1' 
    ,  quark_p2 VARCHAR2(7) PATH '@P2' 
    ,  quark_p3 VARCHAR2(6) PATH '@P3' 
    ,  one  VARCHAR2(1) PATH 'NEST/ONE' 
    ,  two  VARCHAR2(1) PATH 'NEST/TWO' 
    ,  three VARCHAR2(1) PATH 'NEST/THREE' 
    ,  four  VARCHAR2(1) PATH 'NEST/FOUR' 
    ,  five  VARCHAR2(1) PATH 'NEST/FIVE' 
    ,  six  VARCHAR2(1) PATH 'NEST/SIX' 
    ,  seven VARCHAR2(1) PATH 'NEST/SEVEN' 
    ,  eight VARCHAR2(1) PATH 'NEST/EIGHT' 
    ,  nine  VARCHAR2(1) PATH 'NEST/NINE' 
    ) x; 
END; 
/

Это приводит к следующий, что я после:

SQL> SELECT * FROM t 
    2 ; 

QUARK_P1 QUARK_P2 QUARK_P3 O T T F F S S E N 
-------- -------- -------- - - - - - - - - - 
up  charm bottom A B C D E F G H I 
up  strange top  J K L M N O P Q R 

SQL> 

Поскольку уровень «NEST» повторяется так часто, Я бы хотел поместить его в исходный узел и получить те же результаты. Я ищу, чтобы сделать что-то вроде следующего:

BEGIN 
    INSERT INTO t (
     quark_p1 
    , quark_p2 
    , quark_p3 
    , one 
    , two 
    , three 
    , four 
    , five 
    , six 
    , seven 
    , eight 
    , nine 
    ) 
    SELECT x.quark_p1 
    ,  x.quark_p2 
    ,  x.quark_p3 
    ,  x.one 
    ,  x.two 
    ,  x.three 
    ,  x.four 
    ,  x.five 
    ,  x.six 
    ,  x.seven 
    ,  x.eight 
    ,  x.nine 
    -- Notice, I changed the starting node from /BASIS/QUARK to /BASIS/QUARK/NEST.... 
    FROM XMLTABLE('/BASIS/QUARK/NEST' 
    PASSING XMLTYPE (
     '<BASIS> 
      <QUARK P1="up" P2="charm" P3="bottom"> 
       <NEST> 
        <ONE>A</ONE> 
        <TWO>B</TWO> 
        <THREE>C</THREE> 
        <FOUR>D</FOUR> 
        <FIVE>E</FIVE> 
        <SIX>F</SIX> 
        <SEVEN>G</SEVEN> 
        <EIGHT>H</EIGHT> 
        <NINE>I</NINE> 
       </NEST> 
      </QUARK> 
      <QUARK P1="up" P2="strange" P3="top"> 
       <NEST> 
        <ONE>J</ONE> 
        <TWO>K</TWO> 
        <THREE>L</THREE> 
        <FOUR>M</FOUR> 
        <FIVE>N</FIVE> 
        <SIX>O</SIX> 
        <SEVEN>P</SEVEN> 
        <EIGHT>Q</EIGHT> 
        <NINE>R</NINE> 
       </NEST> 
      </QUARK> 
     </BASIS>') 
    -- ...and I changed all the paths here 
    COLUMNS quark_p1 VARCHAR2(4) PATH '../@P1' 
    ,  quark_p2 VARCHAR2(7) PATH '../@P2' 
    ,  quark_p3 VARCHAR2(6) PATH '../@P3' 
    ,  one  VARCHAR2(1) PATH 'ONE' 
    ,  two  VARCHAR2(1) PATH 'TWO' 
    ,  three VARCHAR2(1) PATH 'THREE' 
    ,  four  VARCHAR2(1) PATH 'FOUR' 
    ,  five  VARCHAR2(1) PATH 'FIVE' 
    ,  six  VARCHAR2(1) PATH 'SIX' 
    ,  seven VARCHAR2(1) PATH 'SEVEN' 
    ,  eight VARCHAR2(1) PATH 'EIGHT' 
    ,  nine  VARCHAR2(1) PATH 'NINE' 
    ) x; 
END; 
/

Это, мне кажется, что это должно работать, но я получаю эту ошибку:

FROM XMLTABLE('/BASIS/QUARK/NEST' 
     * 
ERROR at line 28: 
ORA-06550: line 28, column 10: 
PL/SQL: ORA-19110: unsupported XQuery expression 
ORA-06550: line 2, column 5: 
PL/SQL: SQL Statement ignored 


SQL>  

я упускаю что-то простое, или я не могу отсюда?

Спасибо.

+0

Разве это не так, что каждый элемент соответствие '/ BASIS/QUARK/NEST' будет рассматриваться как корень для каждой записи (я основываю это на всех тестах, которые я только что сделал, и я не смог достичь своей цели)? Поэтому вы не сможете ссылаться на родителя, потому что его не будет. Я не понимаю, почему вы хотите изменить свой код? И, еще один момент, чтобы обратиться к родителям, вы должны написать его так: '//../@ P1', с двойным знаком косой черты перед ним. –

ответ

1

я с удивлением обнаружил, из

How to get the name of the parent element in an Oracle XPath expression?

, что это работает, если вы просто поставить «./» в передней части «../»

+0

Вы правы, имея 'COLUMNS quark_p1 VARCHAR2 (4) PATH '//./../@ P1'',', quark_p2 VARCHAR2 (7) PATH' //./../@ P2'' и т. Д. ., в коде работает как объявлено. Благодаря! – Tebbe

Смежные вопросы