我为scott创建了一个路径如下:
 
SQL> CREATE or replace DIRECTORY TEST_DIR AS '/u1/MES/mesora/xml/xml'; 
 
Directory created
 
SQL> grant read,write on directory test_dir to scott;
 
Grant succeeded
以下代码把所有部门信息写入名称为dept.xml的XML文件中:DECLARE
  result CLOB;--存放初始的XML信息
  output_file   UTL_FILE.FILE_TYPE;--文件对象
  xmlstr VARCHAR2(32767);--存放XML
  line   VARCHAR2(2000);--存放一行XML
  line_no INTEGER := 1;
BEGIN
--获取初始的XML,是CLOB数据
  result := DBMS_XMLQuery.getXml('SELECT * FROM dept');
  --获取大对象CLOB中文本信息,注意这里假设所有的XML信息不会超过32767
  xmlstr := DBMS_LOB.SUBSTR(result,32767);
  --UTL_FILE.FOPEN方法创建文件,返回文件对象
  output_file := UTL_FILE.FOPEN('TEST_DIR','dept.xml','w');
  LOOP
    EXIT WHEN xmlstr IS NULL;
    line := SUBSTR(xmlstr,1,INSTR(xmlstr,CHR(10))-1);
    DBMS_OUTPUT.PUT_LINE(line_no || ':' || line);
    --UTL_FILE.PUT写一行信息到文件
    UTL_FILE.PUT(output_file,line || CHR(10));
    xmlstr := SUBSTR(xmlstr,INSTR(xmlstr,CHR(10))+1);
    line_no := line_no + 1;--行号增加
  END LOOP;
  UTL_FILE.FCLOSE(output_file);--关闭文件对象
END;我在/u1/MES/mesora/xml/xml路径下面能够找到dept.xml文件,但是问题是我在/u1/MES/mesora/xml/xml放了一个people.xml文件,我想用程序解析,把people文件写到数据库中,却提示:ora-20100,no such file or directory.
我的解析xml文件的过程函数为:
create or replace procedure xml2table(dir varchar2, inpfile varchar2) is
-- 參數說明:
-- dir      基本目錄,如 'd:\xml\plsql'
-- inpfile  輸入檔案名,不含路徑,如 'people.xml'
-- errfile  錯誤日誌檔,保存解析錯誤資訊, 如 'err.log'p xmlparser.parser;
doc xmldom.DOMDocument;-- 讀取並處理文檔元素
procedure readElements(doc xmldom.DOMDocument) is
  nl     xmldom.DOMNodeList;
  len    number;
  n      xmldom.DOMNode;
  attn   xmldom.DOMNode;
  nnm    xmldom.DOMNamedNodeMap;
  nl2    xmldom.DOMNodeList;
  len2   number;
  strSQL varchar2(1000);begin
   -- 讀取 PERSON 元素
   nl := xmldom.getElementsByTagName(doc, 'PERSON');
   len := xmldom.getLength(nl);   -- 遍曆元素
   for i in 0..len-1 loop
      -- 構造動態 SQL 語句
      strSQL := 'INSERT INTO PEOPLE VALUES (';
      n := xmldom.item(nl, i);
      if xmldom.getNodeName(n)='PERSON' then
         nnm := xmldom.getAttributes(n);  -- 讀取 PERSONID 屬性
         attn := xmldom.item(nnm, 0);
         strSQL := strSQL || '''' || xmldom.getNodeValue(attn) || '''';
      end if;      -- 讀取 PERSON 的子節點
      nl2 := xmldom.getChildNodes(n);
      len2 := xmldom.getLength(nl2);      -- 處理 NAME, ADDRESS, ... 等節點
      for j in 0..len2-1 loop
         n := xmldom.item(nl2, j);
         strSQL := strSQL || ', ''' || xmldom.getNodeValue(xmldom.getFirstChild(n)) || '''';
      end loop;
      -- 完成 動態 SQL 語句的構造
      strSQL := strSQL || ')';
      -- dbms_output.put_line(strSQL);
      -- 執行插入記錄的 SQL 語句
      execute immediate(strSQL);  -- 執行動態 SQL
   end loop;   commit;  -- 提交插入
   dbms_output.put_line('');
end readElements;begin
-- 新建解析器實例
   p := xmlparser.newParser;-- 設置解析器特性
   xmlparser.setValidationMode(p, FALSE);
--   xmlparser.setErrorLog(p, dir || '\' || errfile);
   xmlparser.setBaseDir(p, dir);-- 解析輸入檔
   xmlparser.parse(p, dir || '\' || inpfile);-- 獲取解析後的文檔對象
   doc := xmlparser.getDocument(p);-- 讀取文檔元素
   dbms_output.put_line('讀取文檔元素並保存到表 PEOPLE 中.');
   readElements(doc);-- 釋放資源
   xmldom.freeDocument(doc);end xml2table;
执行语句为:
begin
xml2table('TEST_DIR','people.xml');
end;
请问有没有那位指导为什么?我的执行过程都应该没有问题,因为我在本机数据库都能执行。前面也提出过这个问题,那时候用xmlspy软件导入了。但是现在必须用程序执行,因为以后会有很多数据要导。谢谢!!

解决方案 »

  1.   

    这里错了:
     xmlparser.parse(p, dir ¦ ¦ '\' ¦ ¦ inpfile); dir你定义的是directory,不是路径字符串,怎么可以用||连接那
      

  2.   

    那么请问我该如何定义呢路径字符串呢?Thank you very much!!
      

  3.   

    设置初始化参数:
    utl_file_dir='u1/MES/mesora/xml/xml'程序中:
    xmlparser.parse(p, 'u1/MES/mesora/xml/xml/'|| inpfile); 
      

  4.   

    请问楼上的大侠我已经设置了初始化参数,如下:
    alter system set utl_file_dir='u1/MES/mesora/xml/xml' scope=spfile;然后程序也都按照上面的修改如下:
    create or replace procedure xml2table(dir varchar2, inpfile varchar2) is 
    -- 參數說明: 
    -- dir      基本目錄,如 'd:\xml\plsql' 
    -- inpfile  輸入檔案名,不含路徑,如 'people.xml' 
    -- errfile  錯誤日誌檔,保存解析錯誤資訊, 如 'err.log' p xmlparser.parser; 
    doc xmldom.DOMDocument; -- 讀取並處理文檔元素 
    procedure readElements(doc xmldom.DOMDocument) is 
      nl    xmldom.DOMNodeList; 
      len    number; 
      n      xmldom.DOMNode; 
      attn  xmldom.DOMNode; 
      nnm    xmldom.DOMNamedNodeMap; 
      nl2    xmldom.DOMNodeList; 
      len2  number; 
      strSQL varchar2(1000); begin 
      -- 讀取 PERSON 元素 
      nl := xmldom.getElementsByTagName(doc, 'PERSON'); 
      len := xmldom.getLength(nl);   -- 遍曆元素 
      for i in 0..len-1 loop 
          -- 構造動態 SQL 語句 
          strSQL := 'INSERT INTO PEOPLE VALUES ('; 
          n := xmldom.item(nl, i); 
          if xmldom.getNodeName(n)='PERSON' then 
            nnm := xmldom.getAttributes(n);  -- 讀取 PERSONID 屬性 
            attn := xmldom.item(nnm, 0); 
            strSQL := strSQL ¦ ¦ '''' ¦ ¦ xmldom.getNodeValue(attn) ¦ ¦ ''''; 
          end if;       -- 讀取 PERSON 的子節點 
          nl2 := xmldom.getChildNodes(n); 
          len2 := xmldom.getLength(nl2);       -- 處理 NAME, ADDRESS, ... 等節點 
          for j in 0..len2-1 loop 
            n := xmldom.item(nl2, j); 
            strSQL := strSQL ¦ ¦ ', ''' ¦ ¦ xmldom.getNodeValue(xmldom.getFirstChild(n)) ¦ ¦ ''''; 
          end loop; 
          -- 完成 動態 SQL 語句的構造 
          strSQL := strSQL ¦ ¦ ')'; 
          -- dbms_output.put_line(strSQL); 
          -- 執行插入記錄的 SQL 語句 
          execute immediate(strSQL);  -- 執行動態 SQL 
      end loop;   commit;  -- 提交插入 
      dbms_output.put_line(''); 
    end readElements; begin 
    -- 新建解析器實例 
      p := xmlparser.newParser; -- 設置解析器特性 
      xmlparser.setValidationMode(p, FALSE); 
    --  xmlparser.setErrorLog(p, 'u1/MES/mesora/xml/xml/'  ¦ ¦ errfile); 
      xmlparser.setBaseDir(p, 'u1/MES/mesora/xml/xml/'); -- 解析輸入檔 
      xmlparser.parse(p, 'u1/MES/mesora/xml/xml/' ¦ ¦ inpfile); -- 獲取解析後的文檔對象 
      doc := xmlparser.getDocument(p); -- 讀取文檔元素 
      dbms_output.put_line('讀取文檔元素並保存到表 PEOPLE 中.'); 
      readElements(doc); -- 釋放資源 
      xmldom.freeDocument(doc); end xml2table; 但是还是找不到文件或路径,为什么呀?谢谢!!
      

  5.   

    给出绝对路径啊!
    上面的给你写错了。
    设置初始化参数: 
    utl_file_dir='/u1/MES/mesora/xml/xml' 程序中: 
    xmlparser.parse(p, '/u1/MES/mesora/xml/xml/' ¦ ¦ inpfile); 
      

  6.   

    设置初始化参数: 
    utl_file_dir='u1/MES/mesora/xml/xml' 程序中: 
    xmlparser.parse(p, 'u1/MES/mesora/xml/xml/' ¦ ¦ inpfile); 两次给出的一样呀?我不知道哪里错了,我是设置的绝对路径呀?楼上的大哥不要郁闷,我实在不懂!!谢谢了!!
      

  7.   

    仔细看。再仔细看!再...
    给出绝对路径啊! 
    设置初始化参数: 
    utl_file_dir='/u1/MES/mesora/xml/xml' 程序中: 
    xmlparser.parse(p, '/u1/MES/mesora/xml/xml/' ¦ ¦ inpfile); 
      

  8.   

    alter system set utl_file_dir='/u1/MES/mesora/xml/xml' scope=spfile; xmlparser.parse(p, '/u1/MES/mesora/xml/xml/' ¦ ¦ inpfile); 都已经改为绝对路径了,可是还是不行呀?还是找不到路径或文件名:(
      

  9.   

    改变了utl_file_dir路径现在我这个程序也不能执行了:
    DECLARE
      result CLOB;--存放初始的XML信息
      output_file   UTL_FILE.FILE_TYPE;--文件对象
      xmlstr VARCHAR2(32767);--存放XML
      line   VARCHAR2(2000);--存放一行XML
      line_no INTEGER := 1;
    BEGIN
      --获取初始的XML,是CLOB数据
      result := DBMS_XMLQuery.getXml('SELECT * FROM emp');
      --获取大对象CLOB中文本信息,注意这里假设所有的XML信息不会超过32767
      xmlstr := DBMS_LOB.SUBSTR(result,32767);
      --UTL_FILE.FOPEN方法创建文件,返回文件对象
      output_file := UTL_FILE.FOPEN('TEST_DIR','emp.xml','w');
      LOOP
        EXIT WHEN xmlstr IS NULL;
        line := SUBSTR(xmlstr,1,INSTR(xmlstr,CHR(10))-1);
        DBMS_OUTPUT.PUT_LINE(line_no || ':' || line);
        --UTL_FILE.PUT写一行信息到文件
        UTL_FILE.PUT(output_file,line || CHR(10));
        xmlstr := SUBSTR(xmlstr,INSTR(xmlstr,CHR(10))+1);
        line_no := line_no + 1;--行号增加
      END LOOP;  
      UTL_FILE.FCLOSE(output_file);--关闭文件对象
    END;
    我还能改回原来的值吗?
      

  10.   

    utl_file_dir和你的directory:'TEST_DIR'没有关联的。不会相互影响我测试了下没有问题:
    SELECT * FROM DBA_DIRECTORIES;
    -- OWNER  DIRECTORY_NAME DIRECTORY_PATH
    -- SYS DDD C:\
    DECLARE
      RESULT      CLOB; --存放初始的XML信息 
      OUTPUT_FILE UTL_FILE.FILE_TYPE; --文件对象 
      XMLSTR      VARCHAR2(32767); --存放XML 
      LINE        VARCHAR2(2000); --存放一行XML 
      LINE_NO     INTEGER := 1;
    BEGIN
      --获取初始的XML,是CLOB数据 
      RESULT := DBMS_XMLQUERY.GETXML('SELECT * FROM scott.emp');
      --获取大对象CLOB中文本信息,注意这里假设所有的XML信息不会超过32767 
      XMLSTR := DBMS_LOB.SUBSTR(RESULT, 32767);
      --UTL_FILE.FOPEN方法创建文件,返回文件对象 
      OUTPUT_FILE := UTL_FILE.FOPEN('DDD', 'emp.xml', 'w');
      LOOP
        EXIT WHEN XMLSTR IS NULL;
        LINE := SUBSTR(XMLSTR, 1, INSTR(XMLSTR, CHR(10)) - 1);
        DBMS_OUTPUT.PUT_LINE(LINE_NO || ':' || LINE);
        --UTL_FILE.PUT写一行信息到文件 
        UTL_FILE.PUT(OUTPUT_FILE, LINE || CHR(10));
        XMLSTR  := SUBSTR(XMLSTR, INSTR(XMLSTR, CHR(10)) + 1);
        LINE_NO := LINE_NO + 1; --行号增加 
      END LOOP;
      UTL_FILE.FCLOSE(OUTPUT_FILE); --关闭文件对象 
    END;
    /输出(emp.xml在我创建的ddd目录下也生成了):
    1:<?xml version = '1.0'?>
    2:<ROWSET>
    3:   <ROW num="1">
    4:      <EMPNO>7369</EMPNO>
    5:      <ENAME>SMITH</ENAME>
    6:      <JOB>CLERK</JOB>
    7:      <MGR>7902</MGR>
    8:      <HIREDATE>12/17/1980 0:0:0</HIREDATE>
    9:      <SAL>800</SAL>
    10:      <DEPTNO>20</DEPTNO>
    11:   </ROW>
    12:   <ROW num="2">
    13:      <EMPNO>7499</EMPNO>
    14:      <ENAME>ALLEN</ENAME>
    15:      <JOB>SALESMAN</JOB>
    16:      <MGR>7698</MGR>
    17:      <HIREDATE>2/20/1981 0:0:0</HIREDATE>
    18:      <SAL>1600</SAL>
    19:      <COMM>300</COMM>
    20:      <DEPTNO>30</DEPTNO>
    21:   </ROW>
    22:   <ROW num="3">
    23:      <EMPNO>7521</EMPNO>
    24:      <ENAME>WARD</ENAME>
    25:      <JOB>SALESMAN</JOB>
    26:      <MGR>7698</MGR>
    27:      <HIREDATE>2/22/1981 0:0:0</HIREDATE>
    28:      <SAL>1250</SAL>
    29:      <COMM>500</COMM>
    30:      <DEPTNO>30</DEPTNO>
    31:   </ROW>
    32:   <ROW num="4">
    33:      <EMPNO>7566</EMPNO>
    34:      <ENAME>JONES</ENAME>
    35:      <JOB>MANAGER</JOB>
    36:      <MGR>7839</MGR>
    37:      <HIREDATE>4/2/1981 0:0:0</HIREDATE>
    38:      <SAL>2975</SAL>
    39:      <DEPTNO>20</DEPTNO>
    40:   </ROW>
    41:   <ROW num="5">
    42:      <EMPNO>7654</EMPNO>
    43:      <ENAME>MARTIN</ENAME>
    44:      <JOB>SALESMAN</JOB>
    45:      <MGR>7698</MGR>
    46:      <HIREDATE>9/28/1981 0:0:0</HIREDATE>
    47:      <SAL>1250</SAL>
    48:      <COMM>1400</COMM>
    49:      <DEPTNO>30</DEPTNO>
    50:   </ROW>
    51:   <ROW num="6">
    52:      <EMPNO>7698</EMPNO>
    53:      <ENAME>BLAKE</ENAME>
    54:      <JOB>MANAGER</JOB>
    55:      <MGR>7839</MGR>
    56:      <HIREDATE>5/1/1981 0:0:0</HIREDATE>
    57:      <SAL>2850</SAL>
    58:      <DEPTNO>30</DEPTNO>
    59:   </ROW>
    60:   <ROW num="7">
    61:      <EMPNO>7782</EMPNO>
    62:      <ENAME>CLARK</ENAME>
    63:      <JOB>MANAGER</JOB>
    64:      <MGR>7839</MGR>
    65:      <HIREDATE>6/9/1981 0:0:0</HIREDATE>
    66:      <SAL>2450</SAL>
    67:      <DEPTNO>10</DEPTNO>
    68:   </ROW>
    69:   <ROW num="8">
    70:      <EMPNO>7788</EMPNO>
    71:      <ENAME>SCOTT</ENAME>
    72:      <JOB>ANALYST</JOB>
    73:      <MGR>7566</MGR>
    74:      <HIREDATE>4/19/1987 0:0:0</HIREDATE>
    75:      <SAL>3000</SAL>
    76:      <DEPTNO>20</DEPTNO>
    77:   </ROW>
    78:   <ROW num="9">
    79:      <EMPNO>7839</EMPNO>
    80:      <ENAME>KING</ENAME>
    81:      <JOB>PRESIDENT</JOB>
    82:      <HIREDATE>11/17/1981 0:0:0</HIREDATE>
    83:      <SAL>5000</SAL>
    84:      <DEPTNO>10</DEPTNO>
    85:   </ROW>
    86:   <ROW num="10">
    87:      <EMPNO>7844</EMPNO>
    88:      <ENAME>TURNER</ENAME>
    89:      <JOB>SALESMAN</JOB>
    90:      <MGR>7698</MGR>
    91:      <HIREDATE>9/8/1981 0:0:0</HIREDATE>
    92:      <SAL>1500</SAL>
    93:      <COMM>0</COMM>
    94:      <DEPTNO>30</DEPTNO>
    95:   </ROW>
    96:   <ROW num="11">
    97:      <EMPNO>7876</EMPNO>
    98:      <ENAME>ADAMS</ENAME>
    99:      <JOB>CLERK</JOB>
    100:      <MGR>7788</MGR>
    101:      <HIREDATE>5/23/1987 0:0:0</HIREDATE>
    102:      <SAL>1100</SAL>
    103:      <DEPTNO>20</DEPTNO>
    104:   </ROW>
    105:   <ROW num="12">
    106:      <EMPNO>7900</EMPNO>
    107:      <ENAME>JAMES</ENAME>
    108:      <JOB>CLERK</JOB>
    109:      <MGR>7698</MGR>
    110:      <HIREDATE>12/3/1981 0:0:0</HIREDATE>
    111:      <SAL>950</SAL>
    112:      <DEPTNO>30</DEPTNO>
    113:   </ROW>
    114:   <ROW num="13">
    115:      <EMPNO>7902</EMPNO>
    116:      <ENAME>FORD</ENAME>
    117:      <JOB>ANALYST</JOB>
    118:      <MGR>7566</MGR>
    119:      <HIREDATE>12/3/1981 0:0:0</HIREDATE>
    120:      <SAL>3000</SAL>
    121:      <DEPTNO>20</DEPTNO>
    122:   </ROW>
    123:   <ROW num="14">
    124:      <EMPNO>7934</EMPNO>
    125:      <ENAME>MILLER</ENAME>
    126:      <JOB>CLERK</JOB>
    127:      <MGR>7782</MGR>
    128:      <HIREDATE>1/23/1982 0:0:0</HIREDATE>
    129:      <SAL>1300</SAL>
    130:      <DEPTNO>10</DEPTNO>
    131:   </ROW>
    132:</ROWSET>
      

  11.   

    大哥辛苦了。后面的一个问题解决了。我不能生成xml文件的原因是在调用路径的时候要全都大写虽然创建路径的时候用的是小写名称。因为路径错了后面还有其他的错误,我以为是修改了utl_file_dir路径所导致的呢。现在才明白和那没有关系。
    但是我在解析xml文件的时候:-- 新建解析器實例
       p := xmlparser.newParser;
      xmlparser.setBaseDir(p, dir);
     xmlparser.parse(p, dir || '/' || inpfile);按前面说的 dir是定义的directory,不是路径字符串,不能同后面的文件名用联结符连接,那么我改为绝对路径的话,但是系统不认识这个绝对路径呀?
    -- 新建解析器實例
       p := xmlparser.newParser;
      xmlparser.setBaseDir(p, '/u1/MES/mesora/xml/xml');
     xmlparser.parse(p, '/u1/MES/mesora/xml/xml' || inpfile);这能不能像上面的用utl_file.fopen('dir','dept.xml','r')--打开文件呀?
    还请楼上的大哥多多指点!谢谢!!
      

  12.   

    其实我是用最笨的办法来解决的。我设了两个参数,create or replace procedure xml2table(dir varchar2, dir1 varchar2) is 
    p xmlparser.parser;
    doc xmldom.DOMDocument;-- 讀取並處理文檔元素
    procedure readElements(doc xmldom.DOMDocument) is
      nl     xmldom.DOMNodeList;
      len    number;
      n      xmldom.DOMNode;
      attn   xmldom.DOMNode;
      nnm    xmldom.DOMNamedNodeMap;
      nl2    xmldom.DOMNodeList;
      len2   number;
      strSQL varchar2(1000);begin
       -- 讀取 PERSON 元素
       nl := xmldom.getElementsByTagName(doc, 'PERSON');
       len := xmldom.getLength(nl);   -- 遍曆元素
       for i in 0..len-1 loop
          -- 構造動態 SQL 語句
          strSQL := 'INSERT INTO PEOPLE VALUES (';
          n := xmldom.item(nl, i);
          if xmldom.getNodeName(n)='PERSON' then
             nnm := xmldom.getAttributes(n);  -- 讀取 PERSONID 屬性
             attn := xmldom.item(nnm, 0);
             strSQL := strSQL || '''' || xmldom.getNodeValue(attn) || '''';
          end if;      -- 讀取 PERSON 的子節點
          nl2 := xmldom.getChildNodes(n);
          len2 := xmldom.getLength(nl2);      -- 處理 NAME, ADDRESS, ... 等節點
          for j in 0..len2-1 loop
             n := xmldom.item(nl2, j);
             strSQL := strSQL || ', ''' || xmldom.getNodeValue(xmldom.getFirstChild(n)) || '''';
          end loop;
          -- 完成 動態 SQL 語句的構造
          strSQL := strSQL || ')';
          -- dbms_output.put_line(strSQL);
          -- 執行插入記錄的 SQL 語句
          execute immediate(strSQL);  -- 執行動態 SQL
       end loop;   commit;  -- 提交插入
       dbms_output.put_line('');
    end readElements;begin
    -- 新建解析器實例
       p := xmlparser.newParser;-- 設置解析器特性
       xmlparser.setValidationMode(p, FALSE);
    --   xmlparser.setErrorLog(p, dir || '\' || errfile);
      -- xmlparser.setBaseDir(p, dir);
        xmlparser.setBaseDir(p, dir);
        
    -- 解析輸入檔
      -- xmlparser.parse(p, dir || '/' || inpfile);
        xmlparser.parse(p, dir1);-- 獲取解析後的文檔對象
       doc := xmlparser.getDocument(p);-- 讀取文檔元素
       dbms_output.put_line('讀取文檔元素並保存到表 PEOPLE 中.');
       readElements(doc);-- 釋放資源
       xmldom.freeDocument(doc);end xml2table; 我在调用参数的时候第一个参数输入路径,第二个参数输入带文件名的路径。我把文件直接放在oracle服务器上。这样也不用创建directory,授权了。如果我把文件放在我的电脑上,该如何授权,读取文件解析,现在还是不会.数据库真麻烦,现在真迷茫!以后还请大哥多多指点!