Oracle之xml解析

、 引言

本文主要阐述一种在ORACLE解析XML的实现方法。在oracle8i以及后期的版本中,开始提供了xmldom方式来实现对XML格式数据的处理,但在实际的业务信息系统应用开发中,更多的都习惯在程序中(如java,.net等开发语言提供的xml组件)来解析XML数据,很少直接在ORACLE数据库中来直接解析XML数据。

2、 现象描述

当前,XML数据格式越来越多的应用于各种业务信息系统以及数据交换等应用范围,XML数据变得更加常见以及应用更为广泛。在oracle8i以及后期的版本中,开始提供了xmldom方式来实现对XML格式数据的处理,但在实际的业务信息系统应用开发中,更多的都习惯在程序中(如java,.net等开发语言提供的xml组件)来解析XML数据,很少直接在ORACLE数据库中来直接解析XML数据。

3、 处理过程

 XML数据可以为字符串(适合处理较小的xml数据)、物理文件或CLOB字段(处理较大的xml数据字段);以如下的XML数据为例来描述该解析处理过程。

XML数据格式示例如下:

 

<?<xmlversion="1.0" encoding="GBK" ?>

- <items>

- <unit>

- <item>

<name>单位名称</name>

<value>JXDL</value>

</item>

- <item>

<name>年新增归档数</name>

<value>330</value>

</item>

</unit>

</</items>

 

步骤1:定义或确定要解析的XML规则,如上。

步骤2:创建XML解析器实例XMLPARSER.parser,如下:

    xmlPar XMLPARSER.parser := XMLPARSER.NEWPARSER;

步骤3:定义DOM文档对象,如下:

     doc xmldom.DOMDocument;

步骤4:定义解析XML所需要的其他对象,如下:

 lenUnit integer;

 lenIteminteger;

 unitNodesxmldom.DOMNodeList;

 itemNodesxmldom.DOMNodeList;

 chilNodesxmldom.DOMNodeList;

 tempNode_unitxmldom.DOMNode;

 tempNodexmldom.DOMNode;

 tempArrMapxmldom.DOMNamedNodeMap;

  --================================

  --以下变量用于获取XML节点的值

     name varchar2(50);

     value varchar2(20);

     tmp integer;

--================================

    xmlClobDataclob;

步骤5:获取xml数据,以下假设从数据表的clob字段中获取取,如下:

 selectdatastring into xmlClobData from p_xml_datainfo t where …… ;

步骤6:解析xml数据,如下

  xmlPar := xmlparser.newParser;  

  --xmlparser.parseBuffer(xmlPar,xmlString);--

  xmlparser.parseClob(xmlPar,xmlClobData);

   doc :=xmlparser.getDocument( xmlPar );

-- 释放解析器实例

  xmlparser.freeParser(xmlPar);

-- 获取所有unit元素

  unitNodes := xmldom.getElementsByTagName( doc, 'unit' );

  lenUnit := xmldom.getLength( unitNodes );

--遍历所有unit元素

   FOR iin 0..lenUnit-1

   LOOP

--获取第iunit

    tempNode_unit := xmldom.item( unitNodes, i );    

    itemNodes:=xmldom.getChildNodes(tempNode_unit); 

    lenItem := xmldom.getLength( itemNodes );

    FOR j in 0..lenItem-1

    LOOP

        tempNode := xmldom.item( itemNodes, j );        

     --获取子元素的值

        chilNodes := xmldom.getChildNodes(tempNode);

        tmp := xmldom.GETLENGTH( chilNodes );

        name := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 0 )));

        value := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 1)));

        DBMS_output.PUT_LINE(i||j,name,value);

      end loop;

   END LOOP;

步骤7:释放文档对象

  xmldom.freeDocument(doc);

步骤8:异常与错误处理

   EXCEPTION

   WHEN OTHERS THEN

     DBMS_output.PUT_LINE(SQLERRM);

 

4、 原因分析

目前,在实际的业务信息系统应用开发中,更多的都习惯在程序中(如java,.net等开发语言提供的xml组件)来解析XML数据,很少直接在ORACLE数据库中来直接解析XML数据。

5、 经验总结 

通过在ORACLE数据库中直接解析XML数据,能够更方便灵活的处理xml数据,包括创建方法function,存储过程procedure,以及作业JOB,尤其是处理已经存储在数据表中的XML数据。

 

示例:

 

CREATE OR REPLACE PROCEDURECRM_TEMP.P_sys_EmployeesRoleInsert

(

  strxml VARCHAR2,

  CreateID VARCHAR2,

  CreateIP VARCHAR2,

  CreateMacAddress VARCHAR2,

  CurApmodelID VARCHAR2,

  HRSiteID VARCHAR2    

)

IS

tmpVar NUMBER;

xmlParXMLPARSER.parser := XMLPARSER.NEWPARSER;

docxmldom.DOMDocument;

pNodesxmldom.DOMNodeList;

tempNodexmldom.DOMNode;

tempArrMapxmldom.DOMNamedNodeMap;

 

tempRolelIDnvarchar2(128);

tempWorkNOnvarchar2(128);

 

len int;

n int ;

 

v_RoleModelIDNVARCHAR2(128);

v_RolelID     NVARCHAR2(128);

v_APModelID   NVARCHAR2(128);

v_FunctionCode  NVARCHAR2(128);

v_PAPModelID  NVARCHAR2(128);

v_Count NVARCHAR2(64);

         

I_CreateID        NVARCHAR2(128);

I_CreateIP        NVARCHAR2(128);

I_CreateMacAddress        NVARCHAR2(128);

I_CurApmodelID       NVARCHAR2(128);

I_HRSiteID      NVARCHAR2(128);

 

BEGIN

 

IF strxml is not null THEN

   BEGIN

      I_CreateID :=CreateID;

      I_CreateIP :=CreateIP;

      I_CreateMacAddress :=CreateMacAddress;

      I_CurApmodelID :=CurApmodelID;

      I_HRSiteID :=HRSiteID;   

      v_Count := 0;

      

      XMLPARSER.PARSECLOB(xmlPar,strxml);

     doc:=XMLPARSER.getDocument( xmlPar ); 

    

     XMLPARSER.FREEPARSER(xmlPar);

     pNodes:=xmldom.getElementsByTagName(doc, 'tempWorkNO' );

     len:=xmldom.getLength(pNodes);

    

     tempNode := xmldom.item( pNodes, 0 );

     tempArrMap := xmldom.getAttributes(tempNode);

     tempRolelID:=xmldom.getNodeValue(xmldom.getNamedItem(tempArrMap,'tempRolelID'));

     tempWorkNO := xmldom.getNodeValue(xmldom.getNamedItem(tempArrMap,'tempWorkNO'));

    

     DELETE

        FROM  Sys_RoleEmployees a

        WHERE a.WORKNO = tempWorkNO AND a.HRSiteID=I_HRSiteID;  

       

     FOR i in 0..len-1

     LOOP

       tempNode := xmldom.item( pNodes, i );

       tempArrMap := xmldom.getAttributes(tempNode);

      

       tempRolelID:=xmldom.getNodeValue(xmldom.getNamedItem(tempArrMap,'tempRolelID'));

       tempWorkNO := xmldom.getNodeValue(xmldom.getNamedItem(tempArrMap,'tempWorkNO'));

      

       INSERT INTO Sys_RoleEmployees

       (

        RoleEmployeesID,

        RolelID,

        WORKNO,

        createID,

        CreateIP,

        CreateMacAddress,

        CurApmodelID,

        HRSiteID

       )

       VALUES

       (

       SYS_GUID(),

       tempRolelID,

       tempWorkNO,

       I_CreateID,

       I_CreateIP,

       I_CreateMacAddress,

       I_CurApmodelID,

       I_HRSiteID

       );

      Commit;

     

     END LOOP;

  

   END;

END IF;

 

    EXCEPTION

    WHEN NO_DATA_FOUND THEN

    NULL;

    WHEN OTHERS THEN

    ROLLBACK;

    RAISE;

 

END P_sys_EmployeesRoleInsert;

/

 

示例2.

 

 1 <?xml version="1.0"?>
 2 <PEOPLE>
 3     <PERSON PERSONID="E01">
 4         <NAME>Tony Blair</NAME>
 5         <ADDRESS>10 Downing Street, London, UK</ADDRESS>
 6         <TEL>(061) 98765</TEL>
 7         <FAX>(061) 98768</FAX>
 8         <EMAIL>blair@everywhere.com</EMAIL>
 9     </PERSON>
10     <PERSON PERSONID="E02">
11         <NAME>Bill Clinton</NAME>
12         <ADDRESS>White House, USA</ADDRESS>
13         <TEL>(001) 6400 98765</TEL>
14         <FAX>(001) 6400 98769</FAX>
15         <EMAIL>bill@everywhere.com</EMAIL>
16     </PERSON>
17     <PERSON PERSONID="E03">
18         <NAME>Tom Cruise</NAME>
19         <ADDRESS>57 Jumbo Street, New York, USA</ADDRESS>
20         <TEL>(001) 4500 67859</TEL>
21         <FAX>(001) 4500 67895</FAX>
22         <EMAIL>cruise@everywhere.com</EMAIL>
23     </PERSON>
24     <PERSON PERSONID="E04">
25         <NAME>Linda Goodman</NAME>
26         <ADDRESS>78 Crax Lane, London, UK</ADDRESS>
27         <TEL>(061) 54 56789</TEL>
28         <FAX>(061) 54 56772</FAX>
29         <EMAIL>linda@everywhere.com</EMAIL>
30     </PERSON>
31 </PEOPLE>


我以scott用户为例,新建表:

1 CREATE TABLE PEOPLE
2 (
3   PERSONID VARCHAR2(4PRIMARY KEY,
4   NAME VARCHAR2(50),
5   ADDRESS VARCHAR2(200),
6   TEL VARCHAR2(20),
7   FAX VARCHAR2(20),
8   EMAIL VARCHAR2(100)
9 );


解析并持久化的存储过程代码:

 

 

*file_path     需要解析的XML文件路径 如:D:\OracleTest\people.xml
 3 *log_path      
保存日志的文件的路径  : D:\OracleTest\xmllog.txt
 4
 **/
 5 
 6 CREATE OR REPLACE PROCEDURE addPerson(file_path VARCHAR2,log_path VARCHAR2)
 7 AS
 8 --//XML解析器
 9
 xmlPar XMLPARSER.parser := XMLPARSER.NEWPARSER;
10 --//DOM文档对象
11
 doc xmldom.DOMDocument;
12 len integer;
13 personNodes xmldom.DOMNodeList;
14 chilNodes xmldom.DOMNodeList;
15 tempNode xmldom.DOMNode;
16 tempArrMap xmldom.DOMNamedNodeMap;
17 --================================
18
 --以下变量用于获取XML节点的值
19
 pid varchar2(4);
20 name varchar2(50);
21 address varchar2(200);
22 tel varchar2(20);
23 fax varchar2(20);
24 email varchar(100);
25 tmp integer;
26 --================================
27
 BEGIN
28   xmlPar := xmlparser.newParser;
29   xmlparser.setErrorLog( xmlPar, log_path);
30   xmlparser.parse(xmlPar, file_path);
31   doc := xmlparser.getDocument( xmlPar );  
32   -- 释放解析器实例
33
   xmlparser.freeParser(xmlPar);
34   -- 获取所有PERSON元素
35
   personNodes := xmldom.getElementsByTagName( doc, 'PERSON' );
36   len := xmldom.getLength( personNodes );
37   --遍历所有PERSON元素
38
   FOR i in 0..len-1
39   LOOP
40    --获取第iPERSON
41
     tempNode := xmldom.item( personNodes, i );
42     --所有属性
43
     tempArrMap := xmldom.getAttributes(tempNode);
44     --获取PERSONID的值
45
     pid := xmldom.getNodeValue(xmldom.getNamedItem(tempArrMap,'PERSONID'));
46     --获取子元素的值
47
     chilNodes := xmldom.getChildNodes(tempNode);
48     tmp := xmldom.GETLENGTH( chilNodes );
49     name := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 0 )));
50     address := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 1 )));
51     tel := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 2 )));
52     fax := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 3 )));
53     email := xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item( chilNodes, 4 )));
54     --插入数据
55
     INSERT INTO PEOPLE VALUES (pid,name,address,tel,fax,email);
56     COMMIT;
57   END LOOP;
58   -- 释放文档对象
59
   xmldom.freeDocument(doc);
60   EXCEPTION
61    WHEN OTHERS THEN
62      DBMS_output.PUT_LINE(SQLERRM);
63 END addPerson;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值