I used the XML Binding Wizard to create a descendant of TXMLDocument. The files generated by this class would declare the namespace in the root node and create just plain, unadorned nodes for the rest of the document.
<?xml version="1.0"?>
<RootNode xmlns="URL" xmlns:xsi="URL" xsi:schemaLocation="URL">
<SomeNode>
<AnotherNode>Value</AnotherNode>
</SomeNode>
</RootNode>
I've had no trouble reading or validating this at all. However, the processor where these files are sent now requires each node to have the namespace prefixed in order to process files correctly.
<?xml version="1.0"?>
<NS:RootNode xmlns:NS="URL" xmlns:xsi="URL" xsi:schemaLocation="URL">
<NS:SomeNode>
<NS:AnotherNode>Value</NS:AnotherNode>
</NS:SomeNode>
</NS:RootNode>
How do I accomplish this with my TXMLDocument descendant? I hope it doesn't involve hand editing 10000 lines of generated code.
Ok, the solution took a long time to discover but was surprisingly simple.
The code generated by XML Data Binding Wizard will create xml using the default namespace. You can see this by examining the Get
, Load
and New
functions in the generated unit. All three make calls to GetDocBinding
, passing in TargetNamespace
as the final parameter. TargetNamespace
is a global constant string with the URI extracted from the schema or xml document you fed to the Binding Wizard.
Because TargetNamespace
is assigned to the root element as the default namespace no child elements will have a prefix.
The way to do this:
FDocumentName :=
NewXMLDocument.GetDocBinding(
'ns:DocumentName', // <-- Just add the prefix to the root node.
TXMLDocumentName,
TargetNamespace) as IXMLDocumentName;
Now the root node will look like:
<ns:DocumentName xmlns:ns="URI">
And all child nodes will have the prefix when they are created.