我在更新oracle数据库中的大型XML文件时遇到了问题。
这个XML描述了数据库结构,我必须更新很多节点。我遇到的问题是,当我必须更新节点中的<![CDATA[...]]>
时。我常用的查询是这样的:
UPDATE XML_TABLE set XML_TABLE.xml =
(select XMLQuery('copy $tmp := . modify
(for $i in $tmp/MODEL/ERD/ENTITIES/ENTITY[upper-case(NAME) = "SOME_TABLE"]NOTES/text()
return replace value of node $i with $p0)
return $tmp'
PASSING x.xml, '<![CDATA[ new text value ]]>' as "p0" RETURNING CONTENT) FROM XML_TABLE x )
我选择这种查询的原因是我可以让它一次更新多个节点:
select xmlquery(' copy $tmp := . modify
((for $j in $tmp/MOD (...)return insert node $p1 as last into $j),
(for $j in $tmp/MODEL(...)return insert node $p2 as last into $j),
(for $j in $tmp/MODEL(...)return insert node $p3 as last into $j))
return $tmp'
passing x.xml, 'whatever1' as "p1",
'something1' as "p2",
'sth2' as "p3"
returning content
)
From XML_TABLE x
不幸的是,我不能用<![CDATA[...]]>
更新节点。将"<"one_answers">"符号替换为"<
"one_answers">
"。我不能封装CDATA在XMLTYPE: XMLTYPE('<![CDATA[...]]>
),因为我得到一个错误。
我可以使用已弃用的函数UPDATEXML()
,但是我需要XPath 1.0中不支持的upper-case()
函数,而且translate()
方法很难看,我不知道在这种情况下如何使用它。当然,我不能保证它不会翻译<>到<
>
.
好的,我使用了一个UPDATEXML()
函数,它对我有用。它不会改变<>到<
>
,但不支持upper-case()
的任何功能(仅支持translate()
)。但是我有能力稍微重建我的程序,现在,我不需要做字符串比较。但是,这不是问题的答案,所以我将把它留作未解决。
CDATA不替换任何东西。它只是一个XML结构,允许您编写纯文本,而不必转义标记。这只是语法上的糖,并且总是等同于将其内容写成文本并进行适当的转义。例如:
<p><![CDATA[Use <p>Hello.</p> to write a paragraph.]]></p>
总是等价于:
<p>Use <p>Hello.</p> to write a paragraph.</p>
当您手工编写文本中包含大量标记的XML文档(如文章)时(如关于XML的文章,在文本中包含XML示例),这有时会很有用。
一旦被解析,CDATA就不会以任何方式被"记录"。一旦传递给XQuery,上述两个示例将产生完全相同的结果(如果将文本复制到输出,则很可能包含<
转义字符)。