zoukankan      html  css  js  c++  java
  • PLSQL解析XML文件

    

    参考网上资料学习汇总

    PL/SQL中利用XML ,Oracle提供了几个组件,让开发人员能轻松地利用XML技术。这些组件包括:

     1.  XML 分析程序。即用来分析、构造和验证XML文档。.

    2. XPath 引擎。 它是使用XpathXML标准的另一个元素)说明语法在内存中搜索XML文档的实用程序。 SLT 处理器。 它在Oracle数据库中支持XSLT,允许您把XML文档转换成其他格式。

    3. XML SQL 实用程序。可以使用SQL产生XML文档,使您可以在Oracle数据库表格中轻松地插入基于XML的数据。 XSQL 页。一项可以汇集声明性XML数据然后通过XSLT公布这些数据的技术。 对于PL/SQL开发人员而言,XML分析程序是最重要的组件。通过它,您可以在Oracle数据库中分析、操纵和转换XML文档。ML分析程序由一套APIs(应用程序编程接口)构成。


    XML结构


    XML常用分析函数


    XMLParser


    包括分析XML文档所需的数据类型和程序。XML Parsing Process


    想知道Oracleparser是如何调用Java来做解析的,请查看Oracle® XMLDeveloper's Kit Programmer's Guide
    10g Release 2 (10.2)

    Part Number B14252-01

    网址: http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14252/adx_j_parser.htm#i1013320

    程序中常用的方法:

    Nodelist := dbms_xslprocessor.selectnodesrootnode, xpath

    dbms_xslprocessor.valueof(节点,节点下的元素,)


    XMLDOM


    包括管理和建立XML文档对象模型(DOM)元素所需的数据类型和程序

    Comparing DOM (Tree-Based) and SAX (Event-Based) APIs

    XMLDOM 这个程序包,其实是通过封装Java 程序来解析XML 的一个PL/SQL的包。具体的作用还是要参考Oracle® Database PL/SQLPackages and Types Reference
    10g Release 2 (10.2)

    Part Number B14258-02

    网址: http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_xmldom.htm


    实例

    <?xml version="1.0" encoding="UTF-8"?>
    <Dfile Status="3">
    <RecCount>200</RecCount>
    <FailCount>1</FailCount>
     <FailInfo>
      <FItem RecErrCode="2901">
         <Item>
           <Name>名称1</Name>
           <Comment>中国银行</Comment>
         </Item>
         <Item>
           <Name>名称2</Name>
           <Comment>建设银行</Comment>
         </Item>
      </FItem>
     </FailInfo>
     <FailInfo>
      <FItem RecErrCode="2902">
         <Item>
           <Name>名称3</Name>
           <Comment>招商银行</Comment>
         </Item>
         <Item>
           <Name>名称4</Name>
           <Comment>平安银行</Comment>
         </Item>
         <Item>
           <Name>名称5</Name>
           <Comment>工商银行</Comment>
         </Item>
      </FItem>
     </FailInfo>
    


    文件的结构



    解析方案


    XML DOM的解析过程中, 如果想找某个节点(Fitem)的属性(RecErrCode),而该节点又不是根节点时,需要从最小的节点往上找父节点,一直到节点Fitem,然后在得到其属性。如果节点是根节点,则可以直接得到根节点的元素和属性的值。

    根据上图所示,我们要找根节点Dfile的元素和属性的值,直接调用


    Oracle通过调用API xmldomdbms_xmlparser来做XML文件的解析。


    . 建立一个Directory ,假如在EBS上实现则需要在EBS DB的服务器上建立路径 如:


      CreateOr Replace Directory FTP_XXX As '/var/tmp/ftp' 直接在APPS下就可以新建


    要查找当前建立的Directory 可以使用 Select * From all_directories 查找当前系统中的所有的 Directory .

    DECLARE
      p_max_size NUMBER := dbms_lob.lobmaxsize;
      src_offset NUMBER := 1;
      dst_offset NUMBER := 1;
      lang_ctx   NUMBER := nls_charset_id('UTF8');
      default_csid CONSTANT INTEGER := nls_charset_id('ZHS16GBK');
      warning         NUMBER;
      l_file_number   PLS_INTEGER := 0;
      l_count         NUMBER;
      l_bfile         BFILE;
      l_clob          CLOB;
      l_commitelement xmldom.domelement;
      l_parser        dbms_xmlparser.parser;
      l_doc           dbms_xmldom.domdocument;
      l_nl            dbms_xmldom.domnodelist;
      l_n             dbms_xmldom.domnode;
      rootnode        dbms_xmldom.domnode;
      parent_rootnode dbms_xmldom.domnode;
      file_length     NUMBER;
      block_size      BINARY_INTEGER;
      l_rootnode_name VARCHAR2(200);
      l_status        VARCHAR2(1000);
      l_recerrcode    VARCHAR2(1000);
      l_failcount     VARCHAR2(200);
      l_reccount      VARCHAR2(200);
      l_name          VARCHAR2(1000);
      l_comments      VARCHAR2(2000);
      l_exists        BOOLEAN;
    
      FUNCTION convertclobtoxmlelement(p_document IN CLOB)
        RETURN xmldom.domelement IS
        x_commitelement xmldom.domelement;
        l_parser        xmlparser.parser;
      BEGIN
        l_parser := xmlparser.newparser;
        xmlparser.parseclob(l_parser, p_document);
        x_commitelement := xmldom.getdocumentelement(xmlparser.getdocument(l_parser));
        RETURN x_commitelement;
      END convertclobtoxmlelement;
    BEGIN
      -- 检查XML是否在路径FTP_XXX下是否存在
      utl_file.fgetattr('FTP_XXX',
                        'simanhe_test.xml',
                        l_exists,
                        file_length,
                        block_size);
    
      IF NOT l_exists THEN
        dbms_output.put_line('XML文件不存在');
        RETURN;
      END IF;
    
      l_bfile := bfilename('FTP_XXX', 'simanhe_test.xml');
      -- 创建一个Clob
      dbms_lob.createtemporary(l_clob, TRUE);
      dbms_lob.open(l_bfile, dbms_lob.lob_readonly);
      -- 将XML文件上载并转换为Clob类型
      dbms_lob.loadclobfromfile(l_clob,
                                l_bfile,
                                p_max_size,
                                dst_offset,
                                src_offset,
                                default_csid, -- UTF8
                                lang_ctx, -- GBK
                                warning);
      l_file_number := dbms_lob.fileexists(l_bfile);
      IF l_file_number = 0 THEN
        dbms_output.put_line('XML文件未被转换成功');
        RETURN;
      END IF;
      dbms_lob.close(l_bfile);
      -- Create a parser.
      l_parser := dbms_xmlparser.newparser;
      BEGIN
        -- Parse the document and create a new DOM document.
        dbms_xmlparser.parseclob(l_parser, l_clob);
      EXCEPTION
        WHEN OTHERS THEN
          dbms_output.put_line('XML文件不完整');
          RETURN;
      END;
      l_doc := dbms_xmlparser.getdocument(l_parser);
      -- Free resources associated with the CLOB and Parser now they are no longer needed.
      dbms_lob.freetemporary(l_clob);
      -- 得到根节点 
      rootnode        := xmldom.makenode(xmldom.getdocumentelement(xmlparser.getdocument(l_parser)));
      l_rootnode_name := xmldom.getnodename(rootnode);
      dbms_output.put_line('XML文件当前的节点名称为 ' || l_rootnode_name);
      -- 得到根节点元素的值
      dbms_xslprocessor.valueof(rootnode, 'RecCount/text()', l_reccount);
      dbms_xslprocessor.valueof(rootnode, 'FailCount/text()', l_failcount);
      dbms_output.put_line('XML文件当前的节点名称为 ' || l_rootnode_name ||
                           '的要素RecCount,FailCount值为' || l_reccount || ',' ||
                           l_failcount);
      -- 得到根节点Dfile的属性Status的值
      l_status := xmldom.getattribute(xmldom.makeelement(rootnode), 'Status');
      dbms_output.put_line('XML文件当前的节点名称为 ' || l_rootnode_name ||
                           '的属性Status的值为' || l_status);
    
      /*取节点Item下各元素的值,先将Items节点全部存放在 l_nl中 */
      l_nl    := dbms_xmldom.getelementsbytagname(l_doc, 'Item');
      l_count := dbms_xmldom.getlength(l_nl);
      FOR cur_emp IN 0 .. dbms_xmldom.getlength(l_nl) - 1 LOOP
        l_n := dbms_xmldom.item(l_nl, cur_emp);
        -- 得到节点Item下元素的值
        dbms_xslprocessor.valueof(l_n, 'Name/text()', l_name);
        dbms_xslprocessor.valueof(l_n, 'Comment/text()', l_comments);
        -- 得到节点Item的父节点FItem
        parent_rootnode := dbms_xmldom.getparentnode(l_n);
        l_rootnode_name := xmldom.getnodename(parent_rootnode);
        -- 得到节点FItem的属性RecErrCode的值
        l_recerrcode := xmldom.getattribute(xmldom.makeelement(parent_rootnode),
                                            'RecErrCode');
      
        dbms_output.put_line('Name :' || l_name || ' ,Comment = ' ||
                             l_comments || ' ,RecErrCode = ' || l_recerrcode);
      
      END LOOP;
      -- 释放分析函数的资源
      dbms_xmlparser.freeparser(l_parser);
      -- 将DOC清空,释放资源
      dbms_xmldom.freedocument(l_doc);
      /*  utl_file.frename('FTP_XXX',
      'simanhe_test.xml',
      'FTP_XXX',
      'D_simanhe_test.xml',
      FALSE);*/ -- XML文件解析完成后重命名
      /*utl_file.fremove('FTP_XXX', 'simanhe_test.xml'); */ -- -- XML文件解析完成后删除文件
    EXCEPTION
      WHEN OTHERS THEN
        dbms_lob.freetemporary(l_clob);
        dbms_xmlparser.freeparser(l_parser);
        dbms_xmldom.freedocument(l_doc);
    END;
    







  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299346.html
Copyright © 2011-2022 走看看