Я не был бы рекомендуемое выполнение этого, но если Вы действительно имеете к тогда расширенной хранимой процедуре 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 выполняет команды в фоновом режиме из-за этого, он не должен использоваться для запущения программ, которые требуют ввода данных пользователем.
Заявление об ограничении ответственности: Протестировано с 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;
Справка Delphi метода TXMLDocument.AddChild говорит (внизу):
Примечание. Не вызывайте AddChild, чтобы добавить дочерний элемент к элементу документа этого документ. При добавлении данных в XML-документ используйте метод AddChild элемента документа или узла в иерархии, который должен быть родительским для нового узла.
И это то, что вы делаете правильно? : -)
Это вводная статья о Программирование XML-документов в Delphi , в которой показано, как вы можете работать со свойством TXMLDocument.DocumentElement вместо вашего определения переменной rootnode в вашем коде.
В моей аналогичной реализации я объявляю res как IXMLDocument вместо TXMLDocument.
var
XMLDoc: IXMLDocument;
.
.
XMLDoc := TXMLDocument.Create(nil);
XMLDoc.Active := True;
.
.
XMLDoc.SaveToFile(Filename);
XMLDoc.Active := False;