使用 pl/sql dom 解析器解析 XML 的最简单方法
Posted
技术标签:
【中文标题】使用 pl/sql dom 解析器解析 XML 的最简单方法【英文标题】:Easiest way to parse XML using pl/sql dom parser 【发布时间】:2012-08-02 17:07:11 【问题描述】:我不知道如何解释,但我会尽力而为。我正在使用 Oracle Apex,并且在我的名为“CLOBTABLE”的表中有 XML,数据类型为 Clob。我已经尝试将 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”表中。我不知道该怎么做。任何帮助将不胜感激。
【问题讨论】:
你的数据库是什么版本的? 我正在使用 Application Express 4.1.1.00.23 那是你的 Apex 版本,我想知道 DB 的版本(例如 10g、11gR2、..) 我不确定。因为我正在使用在线工具apex.oracle.com/pls/apex/f?p=4550:1:1431033493681501 【参考方案1】: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 中,您需要进行调整。
【讨论】:
再一次我需要你的帮助,请看我在this page的帖子 @Tom 你能看看我的question 并提供你的建议吗?以上是关于使用 pl/sql dom 解析器解析 XML 的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章