Matching on name() is error-prone, because name() returns the name as it appears in the XML -- if your two inputs bind different prefixes to the namespace name, checking on equality of name() won't succeed. If you change your predicate to
[local-name() = local-name($mpf)
and
namespace-uri() = namespace-uri($mpf)]
your code should work better.
Addendum:
That is, given an XML document Brad1.xml with the following contents:
<INVT_DATA xmlns="http://www.mrbook.com/InventoryData">
<AUTHOR>old author</AUTHOR>
<TITLE>old title</TITLE>
<PUBLISHER>old publisher</PUBLISHER>
</INVT_DATA>
and an XML document Brad2.xml with the following contents:
<id:INVT_DATA xmlns:id="http://www.mrbook.com/InventoryData">
<id:AUTHOR>new author</id:AUTHOR>
<id:PUBLISHER>new publisher</id:PUBLISHER>
</id:INVT_DATA>
the code:
declare namespace invtdata="http://www.mrbook.com/InventoryData";
declare variable $oldXml := doc('.../Brad1.xml');
declare variable $newXml := doc('.../Brad2.xml');
copy $oldInvtData := $oldXml
modify
(
for $mpf in $newXml/invtdata:INVT_DATA/*
let $oldMpf := $oldInvtData/invtdata:INVT_DATA/*
[local-name() = local-name($mpf)
and namespace-uri() = namespace-uri($mpf)]
return if(exists($oldMpf)) then
replace node $oldMpf with $mpf
else insert node $mpf into $oldInvtData
)
return $oldInvtData
evaluates to:
<INVT_DATA xmlns="http://www.mrbook.com/InventoryData"
xmlns:id="http://www.mrbook.com/InventoryData">
<id:AUTHOR>new author</id:AUTHOR>
<TITLE>old title</TITLE>
<id:PUBLISHER>new publisher</id:PUBLISHER>
</INVT_DATA>
If you aren't seeing any nodes replaced at all, one likely cause is an error in an XPath expression (are you sure they are all correct? no typos?); another is failure to bind $oldXml or $newXml as you intend.