Опять про MSXML

svnvlad
Дата: 27.04.2011 17:37:44
Стоит задача создать XML-файл с данными.

Попробовал сделать так, как написано в этой статье:
http://www.codenet.ru/progr/delphi/stat/Using-XML/

Автор очень расхваливает преимущества библиотеки.
Но, во-первых, файл записывается без заголовка XML, там где
<?xml version="1.0" encoding="utf-8" ?>
.
Во-вторых, весь текст, все теги записываются в одну строку, нет даже форматирования текста (отступы, переносы и т.д.).

Я думал, использование библиотеки подразумевает хотя бы эти вещи.

Если так, то не проще ли формировать XML-файл простой вставкой нужных строк в TStringList и записывать в файл?

Как в MSXML задать заголовок файла и форматирование текста?
svnvlad
Дата: 27.04.2011 17:56:43
var
  Doc: DomDocument;
  node: IXMLDomNode;
  txt: IXMLDOMText;
  r: IXMLDomElement;
  sl: TStringList;
begin
  sl := TStringList.Create;
  Doc := coDomDocument.Create;
  SaveDialog1.InitialDir := Conf.Templates.Project.Letters;
  if SaveDialog1.Execute then
    try
      Doc.loadXML('<mail_template/>');
      r := Doc.DocumentElement;

      Node := Doc.CreateElement('title');
      txt := Doc.CreateTextNode('Письмо клиенту о регистрации');
      Node.appendChild(txt);
      r.appendChild(Node);

      Node := Doc.CreateElement('subject');
      txt := Doc.CreateTextNode('Регистация на сайте SITE');
      Node.appendChild(txt);
      r.appendChild(Node);

     // Doc.save(SaveDialog1.FileName);
      sl.Text := '<?xml version="1.0" encoding="UTF-8"?>' + Doc.xml;
      sl.SaveToFile(SaveDialog1.FileName);
    finally
      sl.Free;
    end;
end;

Нужно, чтобы сохраняло в кодировке UTF-8, но сохраняет в Windows-1251. При просмотре результирующего файла в XML-редакторе русские буквы заменяются на ромбики. Если вместо UTF-8 прописать <?xml version="1.0" encoding="Windows-1251"?>, то русские буквы становятся видны.
RIP_RUS
Дата: 27.04.2011 22:16:19
svnvlad,

Procedure SomeProcedure();
var
  XmlDoc: DomDocument;
  Node: IXMLDomNode;
  Root: IXMLDomElement;
begin
  XmlDoc := coDomDocument.Create;
  SaveDialog1.InitialDir :='C:\';
  if SaveDialog1.Execute then
    try
      XmlDoc.appendChild(XmlDoc.createProcessingInstruction('xml','version="1.0" encoding="windows-1251"'));
      XmlDoc.appendChild(XmlDoc.CreateElement('mail_template'));
      Root:=XmlDoc.documentElement;

      Node := XmlDoc.CreateElement('title');
      Node.appendChild(XmlDoc.CreateTextNode('Письмо клиенту о регистрации'));
      Root.appendChild(Node);

      Node := XmlDoc.CreateElement('subject');
      Node.appendChild(XmlDoc.CreateTextNode('Регистрация на сайте SITE'));
      Root.appendChild(Node);

      XmlDoc.Save(SaveDialog1.FileName);
    finally
      Node:=nil;
      Root:=nil;
      XmlDoc:=nil;
    end;
end;
svnvlad
Дата: 28.04.2011 12:47:23
Разобрался. Вот правильный вариант.
var
  Doc: DomDocument;
  Node: IXMLDomNode;
  pi: IXMLDomProcessingInstruction;
  txt: IXMLDOMText;
  r: IXMLDomElement;
begin
  Doc := coDomDocument.Create;
  if SaveDialog1.Execute then
    try
      pi := Doc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"');
      Doc.appendChild(pi);

      Node := Doc.createElement('mail_template'); // Создаем корневой элемент. И никаких Doc.loadXML('<mail_template/>').

      Doc.appendChild(Node);

      r := Doc.DocumentElement;

      Node := Doc.CreateElement('title');

      txt := Doc.CreateTextNode('Письмо клиенту о регистрации');
      Node.appendChild(txt);  // Хотя почему бы эти 2 строки не заменить на Node.Text := 'Письмо клиенту о регистрации';?

      r.appendChild(Node);

      Node := Doc.CreateElement('subject');
      txt := Doc.CreateTextNode('Регистация на сайте SITE');
      Node.appendChild(txt);
      r.appendChild(Node);

      Doc.save(SaveDialog1.FileName);
    finally

    end;

Если нужно отформатировать текст красиво, то
      sl.Text := AnsiToUtf8(FormatXMLData(Doc.XML));
      sl.SaveToFile(SaveDialog1.FileName);
Однако из получившегося файла пропадает encoding="UTF-8".
svnvlad
Дата: 28.04.2011 13:18:18
RIP_RUS,

не заметил вашего поста...
svnvlad
Дата: 28.04.2011 16:25:47
Итоговый рабочий код:
procedure TFrmMail.btnExportClick(Sender: TObject);
var
  XmlDoc: DomDocument;
  Root: IXMLDomElement;
  Node: IXMLDomElement;
  pi: IXMLDomProcessingInstruction;
  txt: IXMLDOMText;
  sl: TStringList;
begin
  sl := TStringList.Create;
  XmlDoc := coDomDocument.Create;
  SaveDialog1.InitialDir := Conf.Templates.Project.Letters;
  if SaveDialog1.Execute then
    try
    //  pi := XmlDoc.createProcessingInstruction('xml', 'version="1.0" encoding="UTF-8"');
    //  XmlDoc.appendChild(pi);

      Node := XmlDoc.createElement('mail_template');

      XmlDoc.appendChild(Node);
      Root := XmlDoc.DocumentElement;

      Root.setAttribute('lang', DQuery.FieldByName('lang').AsString);
      Root.setAttribute('mailtype', DQuery.FieldByName('mailtype').AsString);

      Node := XmlDoc.CreateElement('title');
      txt := XmlDoc.CreateTextNode('Письмо клиенту о регистрации');
      Node.appendChild(txt);
      Root.appendChild(Node);

      Node := XmlDoc.CreateElement('subject');
      txt := XmlDoc.CreateTextNode('Регистация на сайте SITE');
      Node.appendChild(txt);
      Root.appendChild(Node);

      Node := XmlDoc.CreateElement('letter');
      txt := XmlDoc.CreateTextNode(DQuery.FieldByName('letter').AsString);
      Node.appendChild(txt);
      Root.appendChild(Node);

      Node := XmlDoc.CreateElement('itempost');
      txt := XmlDoc.CreateTextNode(DQuery.FieldByName('itempost').AsString);
      Node.appendChild(txt);
      Root.appendChild(Node);

      sl.Text := '<?xml version="1.0" encoding="UTF-8"?>';
      sl.Add(AnsiToUtf8(FormatXMLData(XmlDoc.xml)));
      sl.SaveToFile(SaveDialog1.FileName);
    finally
      Node := nil;
      Root := nil;
      txt := nil;
      XmlDoc := nil;
      sl.Free;
    end;
end;