转义Oracle XDB中的控制字符



我对Oracle的XDB完全陌生,特别是使用它从数据库表生成XML输出,并且我正在开发一个从9i (Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production)到11g (Oracle database 11g Enterprise Edition Release 11.2.0.2.0 - 64位Production)的应用程序。下面是一个小的测试用例,它说明了我遇到的问题:

select xmlelement("test", test) from (select 'a' test from dual);

这工作并给我:

<test>a</test>

但是在11g中,如果我将'a'交换为无效字符,例如U+0013,我会得到以下错误:

ORA-31061: XDB error: special char to escaped char conversion failed.

在9i下,同样的事情成功地工作,没有错误。

显然,理想的答案是有一些验证,以防止控制字符进入我试图转换成XML的简单字符数据,但不幸的是,这超出了我正在做的范围。

这是其他人经历过的事情吗?如果是这样,我可以对我的XML生成脚本进行简单的更改吗?还是我需要做一些其他类型的清理?或者只是在偶尔发生的情况下手动修复问题(这对于我的需求来说是一个非常合理的选择)。

虽然总是在源处固定数据是最佳解决方案,但我也发现在无法控制源处数据的情况下,这很有用:

select xmlelement("test", test) 
  from (select regexp_replace(unistr('a013b'), '[[:cntrl:]]', '') test from dual);

重要的是regexp_replace(your_field, '[[:cntrl::]]', '')从数据中删除控制字符。

U+0013不是XML的有效unicode码点。参见XML中的有效字符。所以11g正确地抛出了一个异常。

SQL> select xmlelement("test", unistr('a013b')) from dual;
ERROR:
ORA-31061: XDB error: special char to escaped char conversion failed.
no rows selected
SQL> select xmlelement("test", unistr('a0aeb')) from dual;
XMLELEMENT("TEST",UNISTR('A0AEB'))
--------------------------------------------------------------------------------
<test>a®b</test>
SQL> 

不知道为什么这个会在9i中通过(我没有可用的),但这可能只是因为Oracle的实现已经发展到更符合标准和/或标准已经发展。

让感兴趣的人继续看看。据我所知,9i只是传递了无效字符,产生了无效的XML。11g抛出一个错误,这可能是更正确的行为,即使它在我的情况下很烦人。

我发现唯一合理的解决方案是在源代码处修复内容。

如果您希望保留换行符,您可以尝试如下:

select xmlelement("test", regexp_replace(test, '[^[:print:]|[:space:]]', '#')) from  
    (select '-   <- to keep line break after weird char
-' test from dual ) 
  • 替换所有^ =>不在集合(打印[:print:]或空格|[:space:]字符)

最新更新