2


我正在尝试解析相当大的 XML 文件。FIle 大到无法使用 VARCHAR2,所以我决定使用 CLOB。代码看起来不错,但我仍然收到错误消息。
这是我正在解析的 xml 文件的示例:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SeznamOvmIndex>
    <Subjekt>
        <Zkratka>CUZK</Zkratka>
        <ICO>00025712</ICO>
        <Nazev>Český úřad zeměměřický a katastrální</Nazev>
        <AdresaUradu>
            <AdresniBod>25133616</AdresniBod>
            <UliceNazev>Pod sídlištěm</UliceNazev>
            <CisloDomovni>1800</CisloDomovni>
            <CisloOrientacni>9</CisloOrientacni>
            <ObecNazev>Praha</ObecNazev>
            <ObecKod>554782</ObecKod>
            <PSC>18200</PSC>
            <KrajNazev>Hlavní město Praha</KrajNazev>
        </AdresaUradu>
        <Email>
            <Polozka>
                <Typ text="podatelna">2</Typ>
                <Email>cuzk@cuzk.cz</Email>
                <Poznamka>Elektronická podatelna ČÚZK</Poznamka>
            </Polozka>
        </Email>
        <TypSubjektu id="11">Orgán státní správy</TypSubjektu>
        <PravniForma type="325">Organizační složka státu</PravniForma>
        <PrimarniOvm>Ano</PrimarniOvm>
        <IdDS>uuaaatg</IdDS>
        <TypDS>OVM</TypDS>
        <StavDS>1</StavDS>
        <StavSubjektu>1</StavSubjektu>
            <DetailSubjektu>http://seznam.gov.cz/ovm/datafile.do?format=xml&amp;service=seznamovm&amp;id=CUZK</DetailSubjektu>
    </Subjekt>
</SeznamOvmIndex>

这是代码:
SET SERVEROUTPUT ON

DECLARE
  xmlClob CLOB;
  xmlFile UTL_FILE.FILE_TYPE;
  x XMLType;
 BEGIN
   xmlFile := UTL_FILE.FOPEN('XMLPARSERADRESYCUZK', 'pokus.xml','R');
  LOOP
    BEGIN
      UTL_FILE.GET_LINE(xmlFile,xmlClob,NULL);
    EXCEPTION WHEN No_Data_Found THEN EXIT; END;
  END LOOP;
  UTL_FILE.FCLOSE(xmlFIle);
  x := XMLType.createXML(xmlClob);
  FOR r IN (
   SELECT ExtractValue(Value(p),'/Subjekt/Zkratka/text()') as kod
         ,ExtractValue(Value(p),'/Subjekt/AdresaUradu/UliceNazev/text()') as ulice
         ,ExtractValue(Value(p),'/Subjekt/AdresaUradu/CisloDomovni/text()') as  cislo_domovni
         ,ExtractValue(Value(p),'/Subjekt/AdresaUradu/CisloOrientacni/text()') as cislo_orientacni
    FROM   TABLE(XMLSequence(Extract(x,'/SeznamOvmIndex/Subjekt'))) p
   WHERE ExtractValue(Value(p),'/Subjekt/Zkratka/text()') = 'CUZK'
   ) LOOP
      dbms_output.put_line(r.kod||' '||r.ulice||' '||r.cislo_domovni||'/'||r.cislo_orientacni);
   END LOOP;
 END;

我认为它应该运行正确,但是当我得到 SQL Developer 时,我得到了:

第 1 行 ORA-06512 错误:无“SYS.XMLTYPE”,第 5 行 ORA-06512:无第 13 行 31011。00000 -“XML 解析失败” *原因:XML 解析器在尝试解析文档时返回错误。*Action:检查要解析的文档是否有效。

4

1 回答 1

4

您正在逐行读取文件,但xmlClob用每一行覆盖您的文件,而不是附加。您可以通过读入缓冲区并追加来构建 CLOB varchar2,但您也可以使用DBMS_LOB内置过程为您完成:

DECLARE
  xmlClob CLOB;
  xmlFile BFILE;
  x XMLType;

  src_offset number := 1 ;
  dest_offset number := 1 ;
  lang_ctx number := DBMS_LOB.DEFAULT_LANG_CTX;
  warning integer;
BEGIN
  xmlFile := BFILENAME('XMLPARSERADRESYCUZK', 'pokus.xml');
  DBMS_LOB.CREATETEMPORARY(xmlClob, true);
  DBMS_LOB.FILEOPEN(xmlFile, DBMS_LOB.FILE_READONLY);
  DBMS_LOB.LOADCLOBFROMFILE(xmlClob, xmlFile, DBMS_LOB.LOBMAXSIZE, src_offset,
    dest_offset, DBMS_LOB.DEFAULT_CSID, lang_ctx, warning);
  x := XMLType.createXML(xmlClob);
  DBMS_LOB.FILECLOSEALL();
  DBMS_LOB.FREETEMPORARY(xmlClob);
  FOR r IN (
...

当我使用它并加载您的文件时,我得到输出:

CUZK Pod smdli.t.m 1800/9

您可能需要围绕DBMS_LOB调用进行一些错误检查,这只是一个简单的演示。

于 2013-06-25T13:55:50.553 回答