I have one CLOB database column which contain a big XML : XML_CONF I usually use the function updateXML to modify specific node of the XML, it works great. But today, I have a lot of trouble with it, because the nodes I want to modify are sometimes empty, and it does not work in this case...
Example of XML with empty textValue :
<ns2:ConfigurationTree xmlns:ns2="com.xxxx" xmlns="com.xxxx.yyyy">
<ns2:ConfigurableProduct ...>...
<ns2:CPNode name="cpX">...
<ns2:FormProperty name="fpX">
<ns2:SingleValuation isCommentUserChoice="false" isValueUserChoice="false" isQtyUserChoice="false">
<ns2:Value>
**<ns2:textValue/>**
</ns2:Value>
</ns2:SingleValuation>
</ns2:FormProperty>
</ns2:CPNode>
</ns2:ConfigurableProduct>
Example of XML with textValue :
<ns2:ConfigurationTree xmlns:ns2="com.xxxx" xmlns="com.xxxx.yyyy">
<ns2:ConfigurableProduct ...>...
<ns2:CPNode name="cpX">...
<ns2:FormProperty name="fpX">
<ns2:SingleValuation isCommentUserChoice="false" isValueUserChoice="false" isQtyUserChoice="false">
<ns2:Value>
**<ns2:textValue>123456</ns2:textValue>**
</ns2:Value>
</ns2:SingleValuation>
</ns2:FormProperty>
</ns2:CPNode>
</ns2:ConfigurableProduct>
For example, to replace the textValue content by "78910", I tried this to handle the two cases :
update T_TABLE set XML_CONF = updatexml(xmltype(XML_CONF),
'//FormProperty[@name="fpX"]//Value/textValue',xmltype('<textValue>78910</textValue>'),
'//FormProperty[@name="fpX"]//Value/textValue/text()','78910',
'xmlns:ns2="com.xxxx" xmlns="xxxx.yyyy"').getClobVal();
But the result broke the XML (no more prefix and xmlns empty in node) :
<ns2:ConfigurationTree xmlns:ns2="com.xxxx" xmlns="com.xxxx.yyyy">
<ns2:ConfigurableProduct ...>...
<ns2:CPNode name="cpX">...
<ns2:FormProperty name="fpX">
<ns2:SingleValuation isCommentUserChoice="false" isValueUserChoice="false" isQtyUserChoice="false">
<ns2:Value>
**<textValue xmlns="">78910</textValue>**
</ns2:Value>
</ns2:SingleValuation>
</ns2:FormProperty>
</ns2:CPNode>
</ns2:ConfigurableProduct>
And if I recall the same request, with a different textValue, it does not update nothing anymore after that... I think it's because the prefix is broken on the node...
I try to do it with XMLQuery (Oracle 12), but it's the same problem.
EDIT
It almost works with :
update T_TABLE set XML_CONF = updatexml(xmltype(XML_CONF),
'//FormProperty[@name="fpX"]//Value/textValue/text()','78910',
'//FormProperty[@name="fpX"]//Value/textValue[not(text())]',xmltype('<textValue>78910</textValue>'),
xmlns:ns2="com.xxxx" xmlns="xxxx.yyyy"' ).getClobVal();
But in output I don't have the new ns2:textValue node, I only have :
<ns2:Value><textValue xmlns="">78910</textValue></ns2:Value>
Why does it break the ns2 prefix, and why it put an empty xmlns attribute ?
If I specify the namespace in the new node it works, but it seems useless because they are already declared in the root node :
update T_TABLE set XML_CONF = updatexml(xmltype(XML_CONF),
'//FormProperty[@name="fpX"]//Value/textValue/text()','78910',
'//FormProperty[@name="fpX"]//Value/textValue[not(text())]',xmltype('<ns2:textValue xmlns:ns2="com.xxxx" xmlns="xxxx.yyyy">78910</ns2:textValue>'),
'xmlns:ns2="com.xxxx" xmlns="xxxx.yyyy"' ).getClobVal();
Give :
<ns2:textValue xmlns:ns2="com.xxxx" xmlns="xxxx.yyyy">78910</ns2:textValue></ns2:Value>