【问题标题】:How to modify header for XML target file using PL/SQL?如何使用 PL/SQL 修改 XML 目标文件的标头?
【发布时间】:2021-09-28 17:09:34
【问题描述】:

我有一个将数据从 Oracle 表导出到 XML 目标的过程。使用的代码是:

ctx := DBMS_XMLGEN.newcontext (v_sql_text);
   DBMS_XMLGEN.setnullhandling (ctx, 0);
   DBMS_XMLGEN.setrowsettag (ctx, 'RENTAL_Set');
   DBMS_XMLGEN.setrowtag (ctx, 'RENTAL_Record');
   xmldoc := DBMS_XMLGEN.getxml (ctx);
   DBMS_XSLPROCESSOR.clob2file (xmldoc,
                                'path',
                                v_file_name,
                                0);
   DBMS_XMLGEN.closecontext (ctx);

我得到目标文件的第一行: <?xml version="1.0"?> 我需要它 <?xml version="1.0" encoding="UTF-8"?>

我怎样才能做到这一点?

【问题讨论】:

    标签: xml oracle plsql procedure


    【解决方案1】:

    DBMS_XMLQuery 用作:

    qryCtx := DBMS_XMLQuery.newContext(v_sql_text);
    
    DBMS_XMLQuery.setNullAttributeIndicator(qryCtx, FALSE);
    DBMS_XMLQuery.setEncodingTag(qryCtx, 'UTF-8');
    DBMS_XMLQuery.setRowsetTag(qryCtx, 'RENTAL_Set');
    DBMS_XMLQuery.setRowTag(qryCtx, 'RENTAL_Record');
    o_results := DBMS_XMLQuery.getXML(qryCtx);
    
    DBMS_XSLPROCESSOR.clob2file (o_results, 'path', v_file_name, 0);
    
    DBMS_XMLQuery.closeContext(qryCtx);
    

    [编辑]

    要保留 DBMS_XMLGEN 结构,请使用此代码块(感谢@AlexPoole):

    declare
       ctx dbms_xmlquery.ctxHandle;
       xmldoc clob;
       v_sql_text varchar2(4000) := 'select * from dual';
    begin
       ctx := DBMS_XMLQuery.newContext(v_sql_text);
    
       DBMS_XMLQuery.useNullAttributeIndicator(ctx, FALSE);
       DBMS_XMLQuery.setEncodingTag(ctx, 'UTF-8');
       DBMS_XMLQuery.setRowsetTag(ctx, 'RENTAL_Set');
       DBMS_XMLQuery.setRowTag(ctx, 'RENTAL_Record');
       DBMS_XMLQuery.setRowIDAttrName(ctx, null);
    
       xmldoc := DBMS_XMLQuery.getXML(ctx);
      -- dbms_output.put_line(xmldoc);
       DBMS_XSLPROCESSOR.clob2file (xmldoc, 'path', v_file_name, 0);
    
       DBMS_XMLQuery.closecontext (ctx);
    end;
    /
    

    【讨论】:

    • 不错...而且更简单!但应该是useNullAttributeIndicator 而不是set...;并且可能想要添加一个setRowIDAttrName 调用以与dbms_xmlgen 结果一致? db<>fiddle
    • 谢谢,DBMS_XMLGEN 也更快。但是看这个Oracle docs的程序名和例子是不一样的。对不起!
    • 哦,是的......它在 19c 文档中仍然是错误的。并且反馈不起作用,因此无法报告 *8-)
    • 我对 pls/sql 和 xml 目标文件非常陌生。您的代码似乎正在运行,但我认为 dbms_output.put_line(xmldoc); 不是正确的方式。获取数据后,我们需要将其发布到路径。现有代码是 DBMS_XSLPROCESSOR.clob2file (xmldoc, 'target_path', v_file_name, 0); 我如何使用 DBMS_XMLQuery 来执行此操作??
    • 我注意到版本号和编码是用单引号引起来的。有什么方法可以用双引号表示它们? @davidm
    【解决方案2】:

    我认为没有办法直接通过dbms_xmlgen。但是您可以通过 BLOB 反弹生成的 XML,并将字符集指定为其中的一部分;而不是:

       xmldoc := DBMS_XMLGEN.getxml (ctx);
    

    您可以使用额外的 XMLType 变量和上下文切换:

    declare
    ...
       xml xmltype;
    begin
    ...
       xml := DBMS_XMLGEN.getxmltype (ctx);
       select xmlserialize(
          content
             xmltype(
                xml.getblobval(nls_charset_id('UTF8')),
                nls_charset_id('UTF8'))
            version '1.0')
       into xmldoc
       from dual;
    

    然后得到:

    <?xml version="1.0" encoding="UTF-8"?>
    <RENTAL_Set>
      <RENTAL_Record>
        ...
      </RENTAL_Record>
    </RENTAL_Set>
    

    db<>fiddle

    xml 值是从同一来源生成的;现在它只是一个 XMLType 而不是 CLOB。然后将其转换为指定字符集 UTF8 的 BLOB。该 BLOC 被转换回 XMLType,但现在它知道字符集。 (感觉应该有一种方法可以跳过其中的一些步骤......)而且因为它现在是基于 BLOB 的 XMLType,所以 XMLSerialize 包含了编码。这会生成一个 CLOB,您可以将其分配给 xmldoc - 然后继续进行文件写入或您需要的任何其他处理。

    【讨论】:

    • 这对我有用,但并不完全。我现在在标题中得到&lt;?xml version="1.0" encoding="US-ASCII"?&gt;
    猜你喜欢
    • 1970-01-01
    • 2015-11-03
    • 2010-10-03
    • 2016-08-26
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多