在 Oracle XDB 中转义控制字符

Posted

技术标签:

【中文标题】在 Oracle XDB 中转义控制字符【英文标题】:Escaping control characters in Oracle XDB 【发布时间】:2011-11-08 09:14:37 【问题描述】:

我对 Oracle 的 XDB 完全陌生,尤其是使用它从数据库表生成 XML 输出,并且正在开发一个从 9i(Oracle9i 企业版版本 9.2.0.5.0 - 生产)迁移到11g(Oracle 数据库 11g 企业版版本 11.2.0.2.0 - 64 位生产)。这是一个小测试用例,说明了我遇到的问题:

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 生成脚本进行简单的更改,或者我是否需要进行其他类型的清理?或者只是在极少数情况下手动解决问题(这对于我的需求来说是一个非常合理的选择)。

【问题讨论】:

【参考方案1】:

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

select xmlelement("test", test) 
  from (select regexp_replace(unistr('a\0013b'), '[[:cntrl:]]', '') test from dual);

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

【讨论】:

【参考方案2】:

U+0013 不是 XML 的有效 unicode 代码点。参见例如Valid characters in XML。所以 11g 正确地引发了异常。

SQL> select xmlelement("test", unistr('a\0013b')) from dual;
ERROR:
ORA-31061: XDB error: special char to escaped char conversion failed.

no rows selected

SQL> select xmlelement("test", unistr('a\00aeb')) from dual;

XMLELEMENT("TEST",UNISTR('A\00AEB'))
--------------------------------------------------------------------------------
<test>a®b</test>

SQL> 

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

你的修正是正确的。

【讨论】:

【参考方案3】:

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

我找到的唯一合理的解决方案是从源头修复内容。

【讨论】:

【参考方案4】:

如果你想保留换行符,你可以尝试如下:

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

【讨论】:

以上是关于在 Oracle XDB 中转义控制字符的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle 的 to_char 中转义非格式字符的最佳方法是啥?

在 findstr 搜索字符串中转义引号

如何在 JSON 中转义特殊字符

在控制台/rake/rails 中转义确保

在正则表达式中转义特殊字符

在 JavaScript 中转义字符串