3

TXMLDocument を使用して XML ドキュメントを作成します。属性値を変更する必要がある場合があります。「ADOM XML v4」DOM ベンダー (Delphi XE2) を使用すると、「名前空間エラー」が発生します。

コード例:

procedure TForm1.Button1Click(Sender: TObject);
var
  XML: TXMLDocument;
  XMLNode, XMLSubNode: 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;
  XMLNode.Attributes['state'] := 0; // Raises "Namespace error"
end;

MSXML を使用すると、すべて正常に動作します。大規模な XML ファイルを生成しており、MSXML よりもはるかに高速であるように思われるため、ADOM XML を使用したいと考えています。

属性値を変更するにはどうすればよいですか?

4

1 に答える 1

2

これはバグです。こちらもかなりメジャー。ADOM XML ベンダーの現在の実装では、null 名前空間で属性を作成すると、その値を変更できません。

Delphi 2010 にバンドルされている、AdomCore_4_3 ユニットの問題のあるコードを次に示します。

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;

上記では、問題はここに分離できます...

    if NamespaceURI = '' then
      raise ENamespace_Err.Create('Namespace error.');

回避策 1

著者の意図はわかりませんが、現状では、このテストはナンセンスです。修正するには、このテストを削除して再コンパイルします。

回避策 2

別の方法として、このように設定する前に属性を削除することもできます...

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;
于 2012-08-03T12:11:16.083 に答える