web-dev-qa-db-ja.com

OracleでXMLエンティティを(読み取り専用アクセスで)Unicode文字に変換する方法は?

読み取り専用アクセスでOracleデータベース(11gリリース2-11.2.0.4)に接続しています。

このデータベースには、一部のデータがXML経由で、またはXMLとしてアップロードされます。また、かなりの数のエントリに、複数のXML(特殊)文字エンティティが&#nnnn;の形式で含まれています。

これまでのところ、これらの&#nnnn;をExcel VBAスクリプトで処理してUnicode文字に変換しましたが、データを(Excelに)エクスポートするために実行しているSQLスクリプトですでにそれを行っています。

このQ&A はほぼ同じ問題をカバーしていますが、私の場合、回答を複製または実装することがまだできていないため、サポートが必要です。

そのQ&Aで受け入れられた回答 には、たとえばcreate tableinsert intodeclareのように、(読み取り専用アクセスでは)使用できないと想定するSQLコマンドが含まれています(間違っていますか?)およびloop

別の答え は、2つのハンディキャップがありますが(1)オンラインフィドルではなく(Oracle SQL Developerで)再現できるという点で機能します。1)ループしないため、特殊な&#nnnn;文字が1つだけ(1回または複数回)含まれ、異なる&#nnnn;文字が含まれていない場合にのみ機能し、2) (非改行スペース)で機能しないこれまでのところ未確認の理由で。

上記のQ&A に基づいて、Oracle 11gでこれらのXML(特殊)文字を読み取り専用アクセスでUnicodeに変換するにはどうすればよいですか?


関連リンク):


(失敗)これまでの試み:

SQL 1

select regexp_replace(s, '&#([0-9]+);', u) from
(select s, unistr('\0' || REPLACE(TO_CHAR(TO_NUMBER(c), 'xxxx'), ' ', '')) u from
(select s, regexp_replace(s, '.*&#([0-9]+);.*', '\1') c from
(select 'Hallöle slovenĈina Hallöle slovenđina' s from dual)))

出力1

HallöleslovenđinaHallöleslovenđina

コメント1

Ĉ(=Ĉ)は、実質的にđ(=đ)によって「上書き」されます。つまり、このスクリプトは1つと同じ特殊文字のみを含むフィールドでのみ機能します。他のすべての特殊文字を1文字で上書きします(これは明らかに望ましくありません)。


SQL 2

select regexp_replace(s, '&#([0-9]+);', u) from
(select s, unistr('\0' || REPLACE(TO_CHAR(TO_NUMBER(c), 'xxxx'), ' ', '')) u from
(select s, regexp_replace(s, '.*&#([0-9]+);.*', '\1') c from
(select 'Hallöle sloven ina' s from dual)))

出力2(エラーメッセージ)

ORA-30186: '\'の後には4つの16進文字または別の '\' 30186が続く必要があります。00000-"'\"の後には4つの16進文字または別の'\'が必要です*原因:SQL関数UNISTRの引数内、「\」の後には4つの16進文字または別の「\」が続く必要があります*アクション:文字列形式を修正します

コメント2

何らかの理由で、改行しないスペース( )は、ここで他の特殊文字とは異なる動作をするようです。おそらくそれはOracleの例外ですか?


SQL 3

select REGEXP_REPLACE(specialCharData,'&#([0-9]+);',unistr('\' || replace(to_char(to_number(regexp_replace(specialCharData, '.*?&#([0-9]+);.*$', '\1')), 'xxx'), ' ', '0')),1,1) as "bla", ................

出力3(エラーメッセージ)

ORA-01722: invalid number
01722. 00000 -  "invalid number"
*Cause:    The specified number was invalid.
*Action:   Specify a valid number.

コメント3

specialCharDataは、私のデータベースのフィールド/列の名前です。


SQL 4

select REGEXP_REPLACE(specialCharData,'&#([0-9]+);',unistr('\' || replace(regexp_replace(specialCharData, '.*?&#([0-9]+);.*$', '\1'), ' ', '0')),1,1) as "specialChar", ................

出力4(エラーメッセージ)

ORA-30186: '\'の後には4つの16進文字または別の '\' 30186が続く必要があります。00000-"'\"の後には4つの16進文字または別の'\'が必要です*原因:SQL関数UNISTRの引数内、「\」の後には4つの16進文字または別の「\」が続く必要があります*アクション:文字列形式を修正します

コメント4

specialCharDataは、私のデータベースのフィールド/列の名前です。ここでは、to_char(to_number(セクションを切り取ってSQL 3をプルーニングしようとしました。あまり役に立たない、おそらく...ランダムなテストのアイデア...

3

データは、XMLタグのない未加工のXMLデータのように見え、翻訳されたテキストではありません。あなたはおそらくそれをfirstで修正する必要があります。

それまでの間、XMLTable()を使用してデータを実行し、変換を行うことができます。

with data as (
  select 'Hallöle slovenĈina Hallöle slovenđina' str from dual
)
select a.str, b.str2
from data a, xmltable( '/'
  passing xmltype( '<dat>' || a.str || '</dat>' )
  columns
   str2 varchar2(4000) path '/dat'
) b

望ましい結果を生成します: enter image description here

1
Michael Kutz

入れ子 replace() を介した「徒歩」での片道:

SELECT replace(replace(replace(col,'&#264';'Ĉ'),'&#273;','đ'),'&#160;',' ')

ループされた正規表現が指定された制限の下で機能しない場合、これは私のベストショットかもしれません...いいえ?

(明らかに、上記をさらに多くの文字に拡張する必要があります...)

0