Проблема, создающая XML-документ с помощью TXMLDocument

Я не был бы рекомендуемое выполнение этого, но если Вы действительно имеете к тогда расширенной хранимой процедуре xp_cmdshell , то, что Вы хотите. Необходимо будет сначала считать содержание файла в переменную и затем использовать что-то вроде этого:

DECLARE @cmd sysname, @var sysname
SET @var = 'Hello world'
SET @cmd = 'echo ' + @var + ' > var_out.txt'
EXEC master..xp_cmdshell @cmd

Примечание: xp_cmdshell выполняет команды в фоновом режиме из-за этого, он не должен использоваться для запущения программ, которые требуют ввода данных пользователем.

8
задан menjaraz 15 March 2012 в 10:39
поделиться

3 ответа

Заявление об ограничении ответственности: Протестировано с D2007.

Ваш код действительно создает XML ( ), как показано в этой измененной функции:

function createXMLDocument(): TXMLDocument;
var
  res: TXMLDocument;
  rootNode: IXMLNode;
  sl : TStringList;
begin
  res := TXMLDocument.Create(nil);
  res.Active := true;
  rootNode := res.AddChild('label');
  // create string for debug purposes
  sl := TStringList.Create; // not needed
  sl.Assign(res.XML);  // Not true: sl is empty after this assignment
  ShowMessage(sl.text);// sl is NOT empty!
  sl.Free;             // don't forget to free it! use try..finally.. to guarantee it!
  //add more elements
//  generateDOM(rootNode);
  Result := res;
end;

Но он требует много замечаний :
- Вам не нужна локальная переменная res, просто используйте Результат.
- Для просмотра XML не требуется дополнительный StringList: Result.Xml.Text
- Не забудьте Освободить sl StringList, если вы его создадите.
- Возвращаемый вами XmlDocument непригоден для использования вне функции и дает AV при попытке .

Почему?
Это потому, что XML-документ предназначен для использования как Компонент с владельцем или как Интерфейс в противном случае, чтобы управлять своим срок службы .
Тот факт, что вы используете интерфейс для хранения rootNode, приводит к его уничтожению в конце функции CreateXmlDocument. И если вы посмотрите на код в TXMLNode._Release , вы увидите, что он запускает TXMLDocument._Release , который вызывает Destroy, если нет владельца XMLDocument (или интерфейса, содержащего ссылку на него).
Вот почему XMLDocument является допустимым и заполняется внутри функции CreateXMLDocument, но недоступен за его пределами, если вы не вернете интерфейс или не предоставите владельца .

См. альтернативные решения ниже :

function createXMLDocumentWithOwner(AOwner: TComponent): TXMLDocument;
var
  rootNode: IXMLNode;
begin
  Assert(AOwner <> nil, 'createXMLDocumentWithOwner cannot accept a nil Owner');
  Result := TXMLDocument.Create(AOwner);
  Result.Active := True;
  rootNode := Result.AddChild('label');
  OutputDebugString(PChar(Result.Xml.Text));
  //add more elements
//  generateDOM(rootNode);
end;

function createXMLDocumentInterface(): IXMLDocument;
var
  rootNode: IXMLNode;
begin
  Result := TXMLDocument.Create(nil);
  Result.Active := True;
  rootNode := Result.AddChild('label');
  OutputDebugString(PChar(Result.Xml.Text));
  //add more elements
//  generateDOM(rootNode);
end;


procedure TForm7.Button1Click(Sender: TObject);
var
  doc: TXmlDocument;
  doc2: IXMLDocument;
begin
  ReportMemoryLeaksOnShutdown := True;

  doc := createXMLDocument;
  // ShowMessage( doc.XML.Text ); // cannot use it => AV !!!!
  // already freed, cannot call doc.Free;

  doc := createXMLDocumentWithOwner(self);
  ShowMessage( doc.XML.Text );

  doc2 := createXMLDocumentInterface;
  ShowMessage( doc2.XML.Text );
end;
12
ответ дан 5 December 2019 в 09:26
поделиться

Справка Delphi метода TXMLDocument.AddChild говорит (внизу):

Примечание. Не вызывайте AddChild, чтобы добавить дочерний элемент к элементу документа этого документ. При добавлении данных в XML-документ используйте метод AddChild элемента документа или узла в иерархии, который должен быть родительским для нового узла.

И это то, что вы делаете правильно? : -)

Это вводная статья о Программирование XML-документов в Delphi , в которой показано, как вы можете работать со свойством TXMLDocument.DocumentElement вместо вашего определения переменной rootnode в вашем коде.

4
ответ дан 5 December 2019 в 09:26
поделиться

В моей аналогичной реализации я объявляю res как IXMLDocument вместо TXMLDocument.

var
   XMLDoc: IXMLDocument;
.
.
   XMLDoc := TXMLDocument.Create(nil);
   XMLDoc.Active := True;
.
.
   XMLDoc.SaveToFile(Filename);
   XMLDoc.Active := False;
2
ответ дан 5 December 2019 в 09:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: