迷彩风情的gravatar头像
迷彩风情 2014-08-19 17:11:09

java读取Oracle11g clob存的xml文件,然后解析出来插入到另外一个表中

求解答:读取clob存的xml文件,然后解析出来插入到另外一个表中

大致的要求如下:
已有程序可以把xml文件写入到表1中的clob字段中,我需要写一个触发器把写入的xml文件的内容提取出来,然后解析出来后写入到另外一个表中去。
表1的表结构为:
列名        数据类型        长度        允许空
id        Varchar2        25        否
commandId        Varchar2        20                是
data        clob        -----        是
stamp        Varchar2        20        是

Temp表结构(监测设备上报的数据自动写入此表)


Data字段的字符串格式如下:

<com.automic.commu.interf.DataPackage>   //说明: 此为根节点
  <___DOLLAR_2>com.automic.commu.protocols.auto3_0.DataAuto3_0</___DOLLAR_2>
  <___DOLLAR_1 class="com.automic.commu.protocols.auto3_0.DataAuto3_0-array">
    <com.automic.commu.protocols.auto3_0.DataAuto3_0>   //说明:此处为一条记录开始
      <meterStatus>0</meterStatus>
      <sensorStatus>0</sensorStatus>
      <powerStatus>0</powerStatus>
      <storePowerVoltStatus>0</storePowerVoltStatus>
      <pumpStatus>1</pumpStatus>
      <doorStatus>0</doorStatus>
      <remainWaterStatus>0</remainWaterStatus>
      <waterLevelStatus>1</waterLevelStatus>
      <icCardStatus>1</icCardStatus>
      <accumulateFlux>72186.0</accumulateFlux>
      <instantFlux>0.0</instantFlux>
      <remainWater>-72186.0</remainWater>
      <waterLevel>0.0</waterLevel>
      <dateTime>071102 16</dateTime>
      <meterModel>00</meterModel>
      <hasEvent>0</hasEvent>
      <eventFirstCount>0</eventFirstCount>
      <eventSecondCount>0</eventSecondCount>
      <eventFlag>00000000000000000000000000000000</eventFlag>
      <AutoReportType>1</AutoReportType>
      <gprsId>15832897782</gprsId>
      <meterNo>2310008899</meterNo>
      <dataType>10000</dataType>
      <orderSucc>0</orderSucc>
</com.automic.commu.protocols.auto3_0.DataAuto3_0> //说明:此处为一条记录结束标志
<com.automic.commu.protocols.auto3_0.DataAuto3_0>   //说明:此处为一条记录开始
      <meterStatus>0</meterStatus>
      <sensorStatus>0</sensorStatus>
      <powerStatus>0</powerStatus>
      <storePowerVoltStatus>0</storePowerVoltStatus>
      <pumpStatus>1</pumpStatus>
      <doorStatus>0</doorStatus>
      <remainWaterStatus>0</remainWaterStatus>
      <waterLevelStatus>1</waterLevelStatus>
      <icCardStatus>1</icCardStatus>
      <accumulateFlux>72186.0</accumulateFlux>
      <instantFlux>0.0</instantFlux>
      <remainWater>-72186.0</remainWater>
      <waterLevel>0.0</waterLevel>
      <dateTime>071102 16</dateTime>
      <meterModel>00</meterModel>
      <hasEvent>0</hasEvent>
      <eventFirstCount>0</eventFirstCount>
      <eventSecondCount>0</eventSecondCount>
      <eventFlag>00000000000000000000000000000000</eventFlag>
      <AutoReportType>1</AutoReportType>
      <gprsId>15832897782</gprsId>
      <meterNo>2310008899</meterNo>
      <dataType>10000</dataType>
      <orderSucc>0</orderSucc>
    </com.automic.commu.protocols.auto3_0.DataAuto3_0> //说明:此处为一条记录结束标志
<com.automic.commu.protocols.auto3_0.DataAuto3_0>   //说明:此处为一条记录开始
      <meterStatus>0</meterStatus>
      <sensorStatus>0</sensorStatus>
      <powerStatus>0</powerStatus>
      <storePowerVoltStatus>0</storePowerVoltStatus>
      <pumpStatus>1</pumpStatus>
      <doorStatus>0</doorStatus>
      <remainWaterStatus>0</remainWaterStatus>
      <waterLevelStatus>1</waterLevelStatus>
      <icCardStatus>1</icCardStatus>
      <accumulateFlux>72186.0</accumulateFlux>
      <instantFlux>0.0</instantFlux>
      <remainWater>-72186.0</remainWater>
      <waterLevel>0.0</waterLevel>
      <dateTime>071102 16</dateTime>
      <meterModel>00</meterModel>
      <hasEvent>0</hasEvent>
      <eventFirstCount>0</eventFirstCount>
      <eventSecondCount>0</eventSecondCount>
      <eventFlag>00000000000000000000000000000000</eventFlag>
      <AutoReportType>1</AutoReportType>
      <gprsId>15832897782</gprsId>
      <meterNo>2310008899</meterNo>
      <dataType>10000</dataType>
      <orderSucc>0</orderSucc>
    </com.automic.commu.protocols.auto3_0.DataAuto3_0> //说明:此处为一条记录结束标志
  </___DOLLAR_1>
</com.automic.commu.interf.DataPackage>

说明:当监测设备向临时表temp中写入数据时,触发器将temp表中刚写入的记录中data字段字符串中包含的各条记录(若干条,条数不确定)解析出来,将其中有用的信息解析出来写入下面目标表结构中,比如<accumulateFlux>72186.0</accumulateFlux>,将72186.0写入目标表结构中accumulateFlux字段下面,目标表中commandId是temp表中的commandId..

2 目标表结构(CollectData)(触发器解析temp表中data字段的字符串后写入此表中)

列名        数据类型        长度        允许空
commandId        Varchar2        20        是
GPRSid        Varchar2        15        否
sensorStatus        Number        1        是
powerStatus        Number        1        是
remainWaterStatus        Number        1        是
accumulateFlux        Number        (8,2)        是
instantFlux        Number        (5,3)        是
remainWater        Number        (8,2)        是
dateTime        Date                是


我想主要的流程为:
1。读取xml文件
2。解析xml到table2中,不知道现成的工作可以直接用,还是需要按照字符来定义,比如自己解析每一条记录的开始位置等。

多谢了!!

所有回答列表(3)
遇见,的gravatar头像
遇见,  LV36 2014年8月20日

我测试了一下 ,看符合你的要求么

第一个表:xmldata

java读取Oracle11g clob存的xml文件,然后解析出来插入到另外一个表中

java读取Oracle11g clob存的xml文件,然后解析出来插入到另外一个表中

第二个表:xmltest

java读取Oracle11g clob存的xml文件,然后解析出来插入到另外一个表中

接下来是存储过程。

create or replace procedure p_parse (ID in varchar2)    is


--创建xml解析器实例xmlparser.Parser
xmlPar xmlparser.Parser :=xmlparser.newParser;
--定义DOM文档
xDoc xmldom.DOMDocument;
--定义DATA子节点数目变量
lenItme integer;
--定义节点列表,存放DATA节点们
itemNodes xmldom.DOMNodeList;
--定义节点列表,存放DATA子节点们
childNodes xmldom.DOMNodeList;
--定义节点,存放单个DATA节点
itemNode xmldom.DOMNode;
--定义属性变量,存放节点属性
itemArrMap xmldom.DOMNamedNodeMap;
--定义其他变量,存放子节点的值
name varchar(100);
value varchar(100);
newid NUMBER(10);
--定义clob变量,存放xml字符串para_name
xmlStr clob;

begin
         for cur in (select t.xml_data para_name ,t.id   from xmldata t where t.id=ID )
        --从xmldata表中查询数据,id不是唯一标识,一个id可查出多条数据(XML中多条数据),故用loop循环
      loop
          --获取para_name中的xml字符串
          xmlStr:=cur.para_name;
          xmlPar :=xmlparser.newParser;
          --解析xmlStr中xml字符串,并存放到xmlPar中
          xmlparser.parseClob(xmlPar, xmlStr);
          --将xmlPar中的数据转存到dom文档中
          xDoc:=xmlparser.getDocument(xmlPar);
          xmlparser.freeParser(xmlPar);  --释放解析器实例
          --获取所有DATA节点
          itemNodes:=xmldom.getElementsByTagName(xDoc,'DATA');
          --获取DATA节点的个数
          lenItme :=xmldom.getLength(itemNodes);
          --遍历所有的DATA节点
          for i in 0..lenItme-1
          loop
              begin
                   --获取节点列表中的第i个DATA节点
                   itemNode:=xmldom.item(itemNodes,i);
                   --获取第i个DATA节点的所有子节点
                   childNodes:=xmldom.getChildNodes(itemNode);
                   --获取所有子节点的值
                   newid:=xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item(childNodes,0)));
                   name:=xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item(childNodes,1)));
                   value:=xmldom.getNodeValue(xmldom.getFirstChild(xmldom.item(childNodes,2)));
                   --将子节点的值newid,name,value存放到xmltest
                   insert into xmltest values(newid,name,value);
                   commit;
                 end;
             end loop;
      end loop;
      --是否dom文档
      xmldom.freeDocument(xDoc);
      --异常和错误处理
      EXCEPTION
       WHEN OTHERS THEN
       DBMS_output.PUT_LINE(SQLERRM);
end p_parse;

最后是测试:

执行存储过程, 需要输入一个ID  就是你要查询的那个xml串的那个ID  我的是1。

执行后xmltest表为:

java读取Oracle11g clob存的xml文件,然后解析出来插入到另外一个表中

再看看XML字符串。。

<root>
  <DATA>
    <ID>1</ID>
    <NAME>ivan</NAME>
    <VALUE>123</VALUE>
  </DATA>
  <DATA>
    <ID>2</ID>
    <NAME>TEST</NAME>
    <VALUE>777</VALUE>
  </DATA>
  <DATA>
    <ID>3</ID>
    <NAME>newc</NAME>
    <VALUE>666</VALUE>
  </DATA>
</root>

根据楼主要求, 在xmldata添加触发器 after insert 的时候去调用存储过程  把ID传过去就好了。

评论(1) 最佳答案
迷彩风情的gravatar头像
迷彩风情  LV26 2014年8月20日

我现在还没找到好的解决方案,现在正在考虑这个问题!

马鲛鱼的gravatar头像
马鲛鱼  LV18 2014年8月20日

 我正好也有这方面的需求,找到好的解决方案告诉我一下好吗,我考虑的是搞个定时任务,每天晚上跑个批处理任务去批量解析,当然如果你的需求实时性比较高就要另行考虑了。

顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友