This is a bug. A pretty major one too. With the current implementation of the ADOM XML vendor, if you create an attribute in the null namespace, you cannot change its value.
Here is the offending code from the AdomCore_4_3 unit, as bundled with Delphi 2010.
procedure TDomAttr.SetPrefix(const Value: WideString);
begin
if IsReadonly then
raise ENo_Modification_Allowed_Err.Create('No modification allowed error.');
if NodeName = 'xmlns' then
raise ENamespace_Err.Create('Namespace error.');
if NamespaceURI = 'http://www.w3.org/2000/xmlns/' then begin
if Value <> 'xmlns' then
raise ENamespace_Err.Create('Namespace error.');
end else if NamespaceURI = 'http://www.w3.org/XML/1998/namespace' then begin
if Value <> 'xml' then
raise ENamespace_Err.Create('Namespace error.');
end else begin
if NamespaceURI = '' then
raise ENamespace_Err.Create('Namespace error.');
if Value = 'xml' then
raise ENamespace_Err.Create('Namespace error.');
if Value = 'xmlns' then
raise ENamespace_Err.Create('Namespace error.');
end;
if Value = '' then begin
if (NamespaceURI = 'http://www.w3.org/2000/xmlns/') then
raise ENamespace_Err.Create('Namespace error.');
FPrefix := '';
FNodeName := LocalName;
Exit;
end;
if not IsXmlName(Value) then
raise EInvalid_Character_Err.Create('Invalid character error.');
if not IsXmlPrefix(Value) then
raise ENamespace_Err.Create('Namespace error.');
FPrefix := Value;
FNodeName := Concat(Value, ':', LocalName);
end;
In the above, the issue can be isolated to here...
if NamespaceURI = '' then
raise ENamespace_Err.Create('Namespace error.');
Work-around 1
I have no idea what the author's intent was, but as it stands, this test is nonsense. To fix, remove this test and recompile.
Work-around 2
As an alternative, you could delete the attribute before setting like this ...
procedure TForm6.Button1Click(Sender: TObject);
var
XML: TXMLDocument;
XMLNode, XMLSubNode: IXMLNode;
OldAttrib: IXMLNode;
begin
XML := TXMLDocument.Create(nil);
//XML.DOMVendor := GetDOMVendor('MSXML'); // Works using MSXML
XML.DOMVendor := GetDOMVendor('ADOM XML v4');
XML.Active := True;
XMLNode := XML.AddChild('test');
XMLNode.Attributes['state'] := 1;
OldAttrib := XMLNode.AttributeNodes.FindNode('state');
if assigned( OldAttrib) then
XMLNode.AttributeNodes.Remove( OldAttrib);
XMLNode.Attributes['state'] := 0;
end;