更改 XML 节点属性值会导致“命名空间错误”

Posted

技术标签:

【中文标题】更改 XML 节点属性值会导致“命名空间错误”【英文标题】:Changing XML node attribute value gives "Namespace error" 【发布时间】:2012-08-03 11:08:31 【问题描述】:

我使用 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,那么一切正常。我想使用 ADOM XML,因为我正在生成大型 XML 文件,而且它似乎比 MSXML 快得多。

如何更改属性值?

【问题讨论】:

【参考方案1】:

这是一个错误。也是相当重要的一个。使用 ADOM XML 供应商的当前实现,如果您在 null 命名空间中创建属性,则无法更改其值。

这是来自 AdomCore_4_3 单元的违规代码,与 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;

在上面,问题可以隔离到这里......

    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;

【讨论】:

以上是关于更改 XML 节点属性值会导致“命名空间错误”的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:引用 Vuex 存储模块会导致 VueJs 2.5 的命名空间错误

命名空间错误中不存在类型资源

命名空间错误中不存在类型资源

更改XML属性的值会删除其他属性

命名空间错误OfficeOpenXML EPPlus

锂关系命名空间错误?