使用pl / sql dom解析器解析XML的最简单方法

时间:2012-08-02 17:07:12

标签: oracle plsql xml-parsing oracle-apex

我不知道如何解释,但我会尽力而为。我正在使用Oracle Apex并在我的表中使用数据类型为Clob的名为“CLOBTABLE”的XML。我已经尝试过XMLTYPE作为数据类型,但它不接受顶点中的任何数据,所以我使用CLOB当前作为数据类型。现在我想使用xml格式的数据,即

<Row>
    <cellArray>
        <Cell>
            <columnId>1</columnId>
            <valueArray>
                <Value>
                    <value>IR000024575452</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>5</columnId>
            <valueArray>
                <Value>
                    <value>AZ12579856-001</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>2</columnId>
            <valueArray>
                <Value>
                    <value>IT06686</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>9</columnId>
            <valueArray>
                <Value>
                    <value>Hu Mics Metab K</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>8</columnId>
            <valueArray>
                <Value>
                    <value>2006-03-31</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>7</columnId>
            <valueArray>
                <Value>
                    <value>2006-07-27</value>
                </Value>
            </valueArray>
        </Cell>
    </cellArray>
</Row>
<Row>
    <cellArray>
        <Cell>
            <columnId>1</columnId>
            <valueArray>
                <Value>
                    <value>IR000024575452</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>5</columnId>
            <valueArray>
                <Value>
                    <value>AZ12579856-001</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>2</columnId>
            <valueArray>
                <Value>
                    <value>IT06686</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>9</columnId>
            <valueArray>
                <Value>
                    <value>Hu Mics Metab K</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>8</columnId>
            <valueArray>
                <Value>
                    <value>2006-03-31</value>
                </Value>
            </valueArray>
        </Cell>
        <Cell>
            <columnId>7</columnId>
            <valueArray>
                <Value>
                    <value>2006-07-27</value>
                </Value>
            </valueArray>
        </Cell>
    </cellArray>
</Row>

并希望解析此数据并将其插入另一个名为“Hyp”的表中。每个数据对应于数据库表的列id,其余是列值。我尝试了

的Oracle XMLTYPE解析器
DECLARE
    indoc    VARCHAR2(2000);
    indomdoc DBMS_XMLDOM.DOMDocument;
    innode   DBMS_XMLDOM.DOMNode;
    myparser DBMS_XMLPARSER.parser;
    buf      VARCHAR2(2000);
BEGIN
    indoc := '<emp><name>De Selby</name></emp>';
    myParser := DBMS_XMLPARSER.newParser;
    DBMS_XMLPARSER.parseBuffer(myParser, indoc);
    indomdoc := DBMS_XMLPARSER.getDocument(myParser);
    innode := DBMS_XMLDOM.makeNode(indomdoc);
    DBMS_XMLDOM.writeToBuffer(innode, buf);
    DBMS_OUTPUT.put_line(buf);
    DBMS_XMLDOM.freeDocument(indomdoc);
    DBMS_XMLPARSER.freeParser(myParser);
END;

但是现在我想要而不是使用静态内容,即De Selby给出动态内容,即从给出“CLOBTABLE”xml,解析数据并将其插入“Hyp”表中。我不知道怎么做。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:5)

apex.oracle.com有最新的顶级版本和db版本(11gR2 atm)。这允许使用xmltables。

请注意,我必须将标签中的数据包装为有效的xml(否则它将作为主要元素,不解析)

DECLARE
l_xmlclob CLOB := 
'<data>
<Row>
  <cellArray>
    <Cell>
      <columnId>1</columnId>
      <valueArray>
        <Value>
          <value>IR000024575452</value>
        </Value>
      </valueArray>
    </Cell>
    <Cell>
      <columnId>5</columnId>
      <valueArray>
        <Value>
          <value>AZ12579856-001</value>
        </Value>
      </valueArray>
    </Cell>
  </cellArray>
</Row>
<Row>
  <cellArray>
    <Cell>
      <columnId>1</columnId>
      <valueArray>
        <Value>
          <value>IR000024575452</value>
        </Value>
      </valueArray>
    </Cell>
    <Cell>
      <columnId>5</columnId>
      <valueArray>
        <Value>
          <value>AZ12579856-001</value>
        </Value>
      </valueArray>
    </Cell>
  </cellArray>
</Row>
</data>';
BEGIN
   FOR r IN (  SELECT rownum rn, cells
               FROM xmltable('/data/Row' passing XMLTYPE(l_xmlclob)
                                         columns CELLS  XMLTYPE PATH './cellArray')
            )
   LOOP
      DBMS_OUTPUT.PUT_LINE('Row: '||r.rn);      

      FOR c IN ( SELECT colid, colval
                   FROM xmltable('/cellArray/Cell' passing r.cells
                                                   columns COLID NUMBER PATH './columnId',
                                                           COLVAL VARCHAR(20) PATH './valueArray/Value/value')
               )
      LOOP
         DBMS_OUTPUT.PUT_LINE('colid, col value: '||c.colid||', '||c.colval);
      END LOOP;
   END LOOP;
END;

输出:

Row: 1
colid, col value: 1, IR000024575452
colid, col value: 5, AZ12579856-001
Row: 2
colid, col value: 1, IR000024575452
colid, col value: 5, AZ12579856-001

如果你想要实际的列,你可以试试这个:

   FOR r IN (  SELECT rownum rn, cells
               FROM xmltable('/data/Row' passing XMLTYPE(l_xmlclob)
                                         columns CELLS  XMLTYPE PATH './cellArray')
            )
   LOOP
      DBMS_OUTPUT.PUT_LINE('Row: '||r.rn);

      FOR c IN ( SELECT col1, col2, col3, col4, col5, col6
                   FROM xmltable('/cellArray/Cell' passing r.cells
                                                   columns COL1 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "1")]]',
                                                           COL2 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "2")]]',
                                                           COL3 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "3")]]',
                                                           COL4 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "4")]]',
                                                           COL5 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "5")]]',
                                                           COL6 VARCHAR(20) PATH './valueArray/Value/value[//columnId[contains(text(), "6")]]'
                                                   )
               )
      LOOP
         DBMS_OUTPUT.PUT_LINE('col values: col1: '||c.col1||', col2: '||c.col2||', col3: '||c.col3||', col4: '||c.col4||', col5: '||c.col5||', col6: '||c.col6);
      END LOOP;
   END LOOP;

输出:

Row: 1
col values: col1: IR000024575452, col2: , col3: , col4: , col5: , col6: 
col values: col1: , col2: , col3: , col4: , col5: AZ12579856-001, col6: 
Row: 2
col values: col1: IR000024575452, col2: , col3: , col4: , col5: , col6: 
col values: col1: , col2: , col3: , col4: , col5: AZ12579856-001, col6: 

但请注意:您的值是一个奇怪的结构... valuearray&gt; value&gt; value?值包含在值中,为什么单个单元格有多个值(数组)?如果是这种情况,那么在你的xml中,你需要适应。