使用SQL的XMLPARSE读取含特殊字符XML的问题求助
解决方案
思路1:安全转义所有XML特殊字符
XML的预定义特殊字符有5个:&、<、>、"、',必须按**先替换&**的顺序转义,否则会导致转义不完整。修改后的脚本如下:
SELECT * FROM TRANSACTION_DATA_TABLE tdt, XMLTABLE( '$d/*:Request/*:AppData' PASSING XMLPARSE(DOCUMENT REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(tdt.TRAN_DATA, '&', '&'), '<', '<'), '>', '>'), '"', '"'), ''', ''') AS "d" COLUMNS FNAME CHAR(20) PATH '*:FirstName', LNAME CHAR(20) PATH '*:LastName' )
转义后,特殊字符会被转换成XML可识别的实体,不会破坏文档结构,解析器能正常处理。
思路2:截断XML到评论节点之前
既然你只需要XML顶部的FirstName和LastName,且评论节点在文档后方,可以直接截断到评论节点的起始位置,再补全必要的闭合标签保证XML结构完整。假设评论节点为<Comment>,脚本如下:
SELECT * FROM TRANSACTION_DATA_TABLE tdt, XMLTABLE( '$d/*:Request/*:AppData' PASSING XMLPARSE(DOCUMENT SUBSTR(tdt.TRAN_DATA, 1, INSTR(tdt.TRAN_DATA, '<Comment>') - 1) || '</Request></Root>' -- 根据实际XML结构补全闭合标签 AS "d" COLUMNS FNAME CHAR(20) PATH '*:FirstName', LNAME CHAR(20) PATH '*:LastName' )
如果不知道评论节点的具体名称,可以根据XML结构找到AppData节点之后的第一个非目标节点位置,以此作为截断点。
思路3:使用Oracle宽松XML解析模式
Oracle的XMLTYPE支持非严格格式解析,无需手动替换字符,直接忽略部分格式错误。可以用XMLTYPE.CREATEXML或构造函数指定宽松模式:
-- 方法1:使用CREATEXML SELECT * FROM TRANSACTION_DATA_TABLE tdt, XMLTABLE( '$d/*:Request/*:AppData' PASSING XMLTYPE.CREATEXML(tdt.TRAN_DATA, FALSE) AS "d" -- FALSE表示不要求严格格式良好 COLUMNS FNAME CHAR(20) PATH '*:FirstName', LNAME CHAR(20) PATH '*:LastName' ) -- 方法2:使用XMLTYPE构造函数 SELECT * FROM TRANSACTION_DATA_TABLE tdt, XMLTABLE( '$d/*:Request/*:AppData' PASSING XMLTYPE(tdt.TRAN_DATA, 0) AS "d" -- 0代表宽松解析模式 COLUMNS FNAME CHAR(20) PATH '*:FirstName', LNAME CHAR(20) PATH '*:LastName' )
这种方式会自动处理文档中的非法字符,只要目标节点所在的XML片段格式正确,就能正常读取。
思路4:正则表达式清理违规字符
如果只想清理破坏结构的<和>(保留合法XML标签),可以用正则表达式匹配并替换非标签内的特殊字符:
SELECT * FROM TRANSACTION_DATA_TABLE tdt, XMLTABLE( '$d/*:Request/*:AppData' PASSING XMLPARSE(DOCUMENT REGEXP_REPLACE( REPLACE(tdt.TRAN_DATA, '&', '&'), '([^<]|<[^/][^>]*>|<\/[^>]*>)(<|>)([^>]|<[^/][^>]*>|<\/[^>]*>)', '\1\3' ) AS "d" COLUMNS FNAME CHAR(20) PATH '*:FirstName', LNAME CHAR(20) PATH '*:LastName' )
先替换&为&,再用正则保留合法的<xxx>和</xxx>标签,移除其他位置的<和>,避免破坏XML结构。
内容的提问来源于stack exchange,提问作者Hamza Haider
相关产品推荐
相关产品推荐

