How to allow for ampersand in XMLtable()?
-
02-03-2021 - |
سؤال
Starting with this Q&A, note that while this works:
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
… this fails (note the addition of "AT&T and AT & T" to the string):
with data as (
select 'Hallöle AT&T and AT & T 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
with error message:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00242: invalid use of ampersand ('&') character (use &)
Error at line 2
31011. 00000 - "XML parsing failed"
*Cause: XML parser returned an error while trying to parse the document.
*Action: Check if the document to be parsed is valid.
How to fix?
First crude attempt(s):
replace('Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina', ' & ', ' and ')
While this works (at least for "AT & T", it would be desirable to preserve the ampersand in the final output…
المحلول 2
Using '&\2'
as replacement string, backreferencing the 2nd ( ) group:
with data as (
select 'Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina' str from dual
)
select a.str, b.str2
from data a, xmltable( '/'
passing xmltype( '<dat>' || regexp_replace(a.str,'(&)([^#])','&38;\2') || '</dat>' )
columns
str2 varchar2(4000) path '/dat'
) b
نصائح أخرى
The error message clearly told you to use &
.
with data as (
select 'Hallöle AT&T and AT & T 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
;
STR
-------------------------------------------------------------------------
STR2
--------------------------------------------------------------------------------
Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina
Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina
Update (will not work for other special characters such as >
):
with data as (
select regexp_replace('Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina', '(&)([^#])', '\1amp;\2') 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
;
STR
-------------------------------------------------------------------------
STR2
--------------------------------------------------------------------------------
Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina
Hallöle AT&T and AT & T slovenĈina Hallöle slovenđina
I think the simplest solution is to use build-in function DBMS_XMLGEN.CONVERT:
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>' || DBMS_XMLGEN.CONVERT(a.str,0) || '</dat>' )
columns
str2 varchar2(4000) path '/dat'
) b
Function HTF.ESCAPE_SC should also work.
لا تنتمي إلى dba.stackexchange