首页 > 解决方案 > 从文件(Delphi)加载后如何清除XML文档中的子节点?(避免“尝试修改只读节点”错误)

问题描述

我有以下问题。我在几个步骤中创建了一个 XML 文档,并将其保存到 *.html 文件中(在表单执行之后):

procedure TOutputDlg.Execute;
var
  Sl : TStringList;
  I : Integer;
begin
  OKClick := False;
  if ShowModal = mrOK then begin
    if not AddAnother then begin
      SaveDialog1.InitialDir := PrjPath;
      if SaveDialog1.Execute then begin
        InitFile(ExtractFileName(SaveDialog1.FileName));
        if not AddAnotherCheckBox.Checked then
          with XMLDoc.DocumentElement.ChildNodes['head'].ChildNodes['style'] do begin
            Text := StringReplace(Text, 'counter(h1counter) "." ', '', []);
            Text := StringReplace(Text, 'counter-reset: h1counter', 'counter-reset: h2counter', []);
          end
        else                                                                                          //16.09-wip JDC 26/10/2016 Added input box for first number (not included localization of input box label)
          with XMLDoc.DocumentElement.ChildNodes['head'].ChildNodes['style'] do begin
            Text := StringReplace(Text, 'counter-reset: h1counter', 'counter-reset: h1counter '
            + IntToStr(Round(GetRealDlg.Execute('Start numbering at:', 1)) - 1), []);
            if GetRealDlg.CancelClick then
              Exit;
          end;

        for I := 0 to Config.Count - 1 do
          if ModuleCheckListBox.Checked[I] then
            AddModule(Config.Names[I], Config.ValueFromIndex[I]);
        Sl := TStringList.Create;
        try
          Sl.Assign(XMLDoc.XML) ;
//          Sl.Insert(0, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">');
          Sl.Insert(0, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');
          Sl.Insert(0, '<?xml version="1.0"?>');
          Sl.Text := StringReplace(Sl.Text, ' xmlns=""', '', [rfReplaceAll]);
          Sl.Text := StringReplace(Sl.Text, '&amp;', '&', [rfReplaceAll]);
          Sl.WriteBOM := False;
          Sl.SaveToFile(SaveDialog1.FileName, TEncoding.UTF8);
        finally
          Sl.Free;
        end;
        OKClick := True;
      end;
    end else begin
      Form1.OpenExecute(nil);
      XMLDoc.LoadFromFile(SaveDialog1.FileName);
      Body := XMLDoc.DocumentElement.ChildNodes['body'];
      for I := 0 to Config.Count - 1 do
        if ModuleCheckListBox.Checked[I] then
          AddModule(Config.Names[I], Config.ValueFromIndex[I]);
      XMLDoc.SaveToFile(SaveDialog1.FileName);
      OKClick := True;
    end;
    if AddAnotherCheckBox.Checked then begin
      AddAnother := True;
      Execute;
    end;
  end;
  if (not AddAnotherCheckBox.Checked) and OKClick then begin
    ShellExecute(0, 'OPEN', PChar(SaveDialog1.FileName), '', '', SW_SHOWNORMAL);
    OKClick := False;
  end;
  AddAnother := False;
end;

上面的代码块从多个位置(多次)创建 html:

end else begin
  Form1.OpenExecute(nil);
  XMLDoc.LoadFromFile(SaveDialog1.FileName);
  Body := XMLDoc.DocumentElement.ChildNodes['body'];
  for I := 0 to Config.Count - 1 do
    if ModuleCheckListBox.Checked[I] then
      AddModule(Config.Names[I], Config.ValueFromIndex[I]);
  XMLDoc.SaveToFile(SaveDialog1.FileName);
  OKClick := True;
end;

到目前为止,这工作正常。当我尝试为全新的文件制作新的 html 输出时,问题就来了。在那里我初始化 XMLDoc: InitFile(ExtractFileName(SaveDialog1.FileName)); 然后我在ChildNodes.Clear上收到以下错误“尝试修改只读节点” ;线。看起来 XMLDoc 已经加载并且不能再修改了。有什么方法可以卸载它或类似的东西,所以我可以在它上面执行我的 InitFile 过程?

谢谢你的支持!

procedure TOutputDlg.InitFile(FName : WideString);
  procedure locAddStyle(Head: IXMLNode; FileName, Media: WideString);
  var
    Style : IXMLNode;
  begin
    Style :=Head.AddChild('style');
    Style.SetAttribute('type', 'text/css');
    if Media <> '' then
      Style.SetAttribute('media', Media);
    Style.Text := FileToStr(ResPath + FileName);
  end;
var
  Head, N : IXMLNode;
begin
  with XMLDoc do begin
    Active := False;
    Active := True;
    ChildNodes.Clear;
    DocumentElement := AddChild('html');
    DocumentElement.SetAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
    DocumentElement.SetAttribute('xml:lang', Model.OutputLanguage);
    DocumentElement.SetAttribute('lang', Model.OutputLanguage);

    Head := DocumentElement.AddChild('head');
    N := Head.AddChild('title');
    N.Text := 'StrEngS results';
    N := Head.AddChild('meta');
    N.SetAttribute('http-equiv', 'Content-Type');
    N.SetAttribute('content', 'text/html; charset=utf-8');
    locAddStyle(Head, 'strengs.css', '');
    locAddStyle(Head, 'strengs-screen.css', 'screen');
    if UseMathJax then begin
      N := Head.AddChild('script');
      N.SetAttribute('type', 'text/javascript');
      N.SetAttribute('src', 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML');
    end;

{    locAddStyle(Head, 'strengs-print.css', 'print');} // Waitng for browser implementation of @page CSS element

    Body := DocumentElement.AddChild('body');

    // Header
{    N := Body.AddChild('div');
    N.SetAttribute('id', 'print-header');
    M := N.AddChild('img');
    M.SetAttribute('class', 'alignright logo');
    M.SetAttribute('src',
                   ExtractRelativePath(ExtractFileDir(SaveDialog1.FileName) +
                                       '\', ExePath + 'res\Znak.gif'));
    M := N.AddChild('p');
    M.SetAttribute('class', 'alignleft');
    M.Text := LocList['OUTPUT_PROJECT_ID'] + Model.Metadata.ProjectID;

    // Footer
    N := Body.AddChild('div');
    N.SetAttribute('id', 'print-footer');
    M := N.AddChild('p');
    M.SetAttribute('class', 'alignleft');
    M.Text := DateToStr(Date);
    M := N.AddChild('p');
    M.SetAttribute('class', 'alignright');
    M.Text := AU_VERSION_STRING; }    // Waitng for browser implementation of @page CSS element
  end;
end;

标签: htmldelphixmldocument

解决方案


推荐阅读