在oracle SQL中更新XML时如何不转义特殊字符

时间:2014-12-15 14:04:30

标签: sql xml oracle

我在尝试更新oracle中的xmlType值时遇到问题。 我需要修改类似于以下内容的xml:

<a>
  <b>Something to change here</b>
  <c>Here is some narrative containing weirdly escaped &lt;tags>\&lt;/tags> </c>
</a>

我想要实现的是修改&lt; b /&gt;没有修改&lt; c /&gt;

不幸的是在modifyXml之后:

select 
  updatexml(XML_TO_MODIFY, '/a/b/text()', 'NewValue')
from dual;

返回:

<a>
  <b>NewValue</b>
  <c>Here is some narrative containing weirdly escaped &lt;tags&gt;&lt;/tags&gt; </c>
</a>

正如您所看到的,&#39;&gt;&#39;已被逃脱。

xmlQuery(updateXml的新的非弃用版本)也是如此:

select /*+ no_xml_query_rewrite */
      xmlquery(
        'copy $d := .
         modify (
           for $i in $d/a
           return replace value of node $i/b with ''nana''
         )
         return $d'
        passing t.xml_data
         returning content
       ) as updated_doc
from (select xmlType('<a>
      <b>Something to change here</b>
      <c>Here is some narrative containing weirdly escaped \&lt;tags>\&lt;/tags> </c>
    </a>') as xml_data from dual) t
;

使用xmlTransform时,我也会得到相同的结果。 我试着用

disable-output-escaping="yes"

但事实恰恰相反 - 它没有取消&amp; lt; :

select XMLTransform(
    xmlType('<a>
      <b>Something to change here</b>
      <c>Here is some narrative containing weirdly escaped \&lt;tags>\&lt;/tags> </c>
    </a>'),
    XMLType(
'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/a/b">
                <b>
                <xsl:value-of select="text()"/>
                </b>
        </xsl:template>

        <xsl:template match="/a/c">
                <c>
                <xsl:value-of select="text()" disable-output-escaping="yes"/>
                </c>
        </xsl:template>
</xsl:stylesheet>'))
from dual;

返回:

<a>
  <b>NewValue</b>
  <c>Here is some narrative containing weirdly escaped <tags></tags> </c>
</a>

有什么建议吗? 你需要知道两件事:

  1. 我无法修改初始格式 - 它以这种方式来到我身边 我需要保留它。
  2. 原始信息如此之大,正在发生变化 字符串和后面的消息(使用正则表达式作为变通方法)将 不要这么做。

2 个答案:

答案 0 :(得分:1)

您的问题的根源似乎是,如果节点C的原始XML值在值中包含>而不是&gt;而不是Here is some narrative containing weirdly escaped &lt;tags>\&lt;/tags>内,则它不是有效的XML。 (又CDATA section)。

字符串值:

<c>Here is some narrative containing weirdly escaped &amp;lt;tags&gt;\&amp;lt;/tags&gt;</c>

XML格式的

应该是

<c><![CDATA[Here is some narrative containing weirdly escaped &lt;tags>\&lt;/tags>]]></c>

OR

<c>

我要么要求在源头更正XML,要么实现一些方法来自己清理输入,例如将<![CDATA[]]>节点值包装在{{1}}中。如果您需要保存确切的原始值,并且消息很大,那么我能想到的最好的是存储重复副本,原始值为字符串,并存储&#34;已消毒的&#34;值作为XML数据类型。

答案 1 :(得分:0)

最后我们在java的帮助下成功完成了这项工作。 由:

  1. 将xml作为clob阅读
  2. 在java中修改它
  3. 使用java.sql.Connection将其存储回数据库(出于某种原因,如果我们使用的话) JdbcTemplate,它抱怨铸造到Long,这是 表明字符串超过4000字节(谈论干净 错误,所有人都欢呼Oracle)和使用CLOB Type并不是真的 救命。我猜这是一个不同的故事但是)
  4. 存储数据时,oracle不会执行任何魔法,只有更新才会修改转义字符。

    可能不是每个人的答案,但如果你遇到与我们相同的问题,这是一个很好的解决方法。