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

标签 oracle plsql xml-parsing oracle-apex

我不知道如何解释,但我会尽力。我正在使用 Oracle Apex,并且表中有名为“CLOBTABLE”且数据类型为 Clob 的 XML。我已尝试将 XMLTYPE 作为数据类型,但它不接受 apex 中的任何数据,因此我当前使用 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”表中。我不知道该怎么做。任何帮助将不胜感激。

最佳答案

apex.oracle.com 拥有最新的 apex 版本和 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>value>value?值包裹在值中,为什么单个单元格会有多个值(数组)?如果您的 xml 中出现这种情况,您需要进行调整。

关于oracle - 使用 pl/sql dom 解析器解析 XML 的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11782423/

相关文章:

java - Querydsl java按自定义输入列表排序

sql - Pl SQL 对 100 个 View 中的行进行计数,无需联合所有

mysql - 将 MySQL 脚本转换为 ORACLE

sql - Oracle SQL 语法 : With clause

sql - 正则表达式 PL/SQL

C# XML --> 如何获取属于该attributes元素的属性值和xpath

php - 如何使用 PHP 提取 XML 数据数据?

xml - 在TSQL中将JSON转换为XML?

java - 从 Oracle 读取 Windows-1252 格式并使用 Latin1 字符 UTF-8 编码写入 XML 文件

oracle - PLS-00402 : alias required in SELECT list of cursor to avoid duplicate column names