Использование XML в среде DelphiDelphi , Интернет и Сети , XMLИспользование XML в среде Delphi
Оформил: DeeCo Автор: А.Календарев Данная статья является переработанным вариантом материалов по XML-технологии опубликованных на сайте автораПоследнее время много внимания уделяется построение систем электронного бизнеса, или как их еще назыают - B2B (business to business). Учитывая рекомендации по построению обменных потоковых систем координирующего интернет-технологий органа - WWW Consortium: акцент сделан в сторону XML-технологий и построение систем обмена XML-документами. Преимущество использования XML в электронном бизнесе - высокая эффективность B2B систем при низких затратах на ее создание за счет четкого и наглядного представления структурированной информации, возможность использования современных сетевых протоколов и создания бизнес-систем реального времени. Независимость представления информации в виде XML документов позволяет разным, участвующим в электронном бизнесе, фирмам производить независимое друг от друга ПО. Во всех системах обмен, как правило, строится по одинаковой схеме, с использованием HTTP запросов. В качестве протокола защиты информации применяется протокол SSL (но это отдельная тема). Один из возможных вариантов обработки XML сообщения является построение BIN/CGI (ISAPI)-приложений или COM (серверных) компонент, формирующих или обрабатывающих XML-документы. С одной стороны, приложение выступает в качестве клиента, которое в режиме POST выдает HTTP запрос, с другой стороны, находится WEB сервер на стороне которого осуществляется обработка запроса и выдача ответа. В информационном обмене используются XML-документы. Один из наиболее эффективных вариантов реализации - использование существующего XML-парсера, поддерживающего DOM модель. Такой парсер является дистрибутивной поставкой Win`98 или составной частью IE 4,7 и выше (для Win`95) и представляет COM сервер, находящийся в библиотеке msxml.dll. Модель компонентных объектов (COM) - представляет инкапсулированные данные и методы в единую сущность и способ доступа к ним через систему интерфейсов. Средствами Delphi достаточно просто осуществить доступ к классам COM-объекта (в одном COM-сервере может быть включено несколько классов). Доступ к объектам осуществляется путем инициализации экземпляра класса через систему интерфейсов. Описание интерфейсов осуществляется языком определения интерфейсов (IDL), которое возможно осуществить средствами среды автоматически. Средствами Delphi осуществляется импорт из COM-сервера msxml.dll, строится файлы описания интерфейса IDL и файл бинарноого описания типов библиотеки - TLB. Данная операция осуществляется через системное меню: Project | Type Library Import… (рис 1). Далее появляется диалоговое окно (рис 2), в котором необходимо выбрать COM-объект (в нашем случае объект зарегистрирован под именем "Microsoft.XMLDom (Version 2.0)" ) и создать TLB-файл (кнопка Create Unit). Используя TLB-файл, среда генерирует "паскалевский" файл описания COM-сервера - MSXML_TLB.pas
В файле MSXML_TLB.pas описаны все интерфейсы, константы и соклассы COM-сервера. Для доступа к объектам COM-элемента, необходимо в директиве USES добавить имя файла описания библиотеки (MSXML_TLB.pas). Ниже представлена простейшая программа, использующая DOM стандартный анализатор msxml.dll, которая загружает XML-документ и отображает его в элементе текстового поля Memo1. uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, OleServer, MSXML_TLB, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: Tobject); var coDoc: CoDOMDocument; / * объявление сокласса объекта DOMDocument; * / var Doc: IXMLDOMDocument; / * класс, согласованный с интерфейсом IDOMDocument; * / begin Doc := coDoc.Create; / * создание экземпляра объекта DOMDocument; * / Doc.load('data.xml'); / * вызов метода Load экземпляра объекта DOMDocument; * / Memo1.Text := Doc.xml; / * доступ к свойстве xml экземпляра объекта DOMDocument; * / end; end.Концепция DOM - объектная модель документа Каждый XML документ представляется в виде набора множества объектов (классов), с помощью которых возможен доступ к отдельным элементам (полям объекта). DOM - интерфейс описывает доступ как к простым объектам типа DOMString или CharacterData, так и к частям или отдельным элементам XML документа: DOMFragmentElement, DOMNode, DOMElement. Ниже приведены самые важные свойства и методы объектов XMLDOMDocument, XMLDOMNode, XMLDOMNodeList. Необходимо отметить, что представленные ниже методы и функции объектов DOM модели (Document Object Model) используются Microsoft XML-анализатором msxml.dll и несколько шире, чем утвержденная W3C Консорциумом DOM модель. Более полное описание интерфейса DOM объектов можно найти на www.msdn.microsoft.com/xml
Использование XML в бизнесе. Для более ясной картины необходимо пояснение, а зачем все это нужно с тем, что бы понять, как это работает… При построении B2B или корпоративной ERP системы, при организации информационного обмена XML-документами между предприятиями или филиалами пр-я, используются эффективно себя зарекомендовавшая система передачи информации на основе имеющихся WEB серверов по HTTP протоколам. С одной стороны, приложение выступает в качестве клиента, которое в режиме POST выдает HTTP запрос, с другой стороны, находится WEB сервер, на стороне которого осуществляется обработка запроса и выдача ответа. В качестве обмена используются XML-документы. Например, в простой корпоративной ERP системе бухгалтерской программе (АСУ Бухучет) необходимо сформировать некий запрос на выписку накладной и передать его в филиал, который имеет склад (АСУ Склад). АРМ Аналогичная постановка задачи при создании В2В системы, когда Предприятие А запрашивает наличие продукции (делает заказ на приобретение) у Поставщика В. Предприятие А и его программа выступает в качестве клиента. Склад обслуживает Поставщик В, у которого находится складской комплекс БД на SQL сервере. Обмен осуществляется через корпоративный WEB сервер Поставщика В. Ниже представлен следующий типовой алгоритм обмена: Рис 3.
Несколько слов об организации документооборота. Общим правилом разработки системы обмена XML документами является:
Каждый XML документ, подобно HTML документу, должен состоять из заголовка
сообщения (информация заключенная тагами Заголовок (Рис 4), в отличие HTML документа, должен содержать разного рода
служебную информацию, в том числе информацию о типе передаваемого документа и
процессе его обработки. В информационную обработку поступает тело документа,
т.е. содержательная часть обрамленная тагами Для запущенного сервером Процесса, алгоритм обработки предпочтительно (но не обязательно) строить следующим образом: Рис 6.
Некоторые принципиальные моменты
при создании клиентской части
Как уже пояснялось, при создание XML-документа используется его представление в виде DOM модели. Ниже приведен пример части текста Delphi программы создания заголовка xml сообщения. procedure TThread1.HeaderCreate(Sender: Tobject); var coDoc : CoDomDocument ; // объявление сокласса, необходим для создания Doc : DomDocument ; // объекта XMLDomDocument r : IXMLDOMElement; // объявление объектов DOMElement Node : IXMLDOMElement; // txt : IXMLDOMText; // DOMText attr : IXMLDOMAttribute; // DOMAttribute begin Doc:=coDoc.Create; // создание документа DOM Doc.Set_async(false); // установка синхронного режима обрабработки Doc.LoadXML('<Header/>'); // начальная инициация DOM документа r:=Doc.Get_documentElement; // получение адреса корневого элемента Node := Doc.createElement ( 'Sender'); // создание DOMElement (таг <Sender>) txt := Doc.createTextNode( 'ООО "Тайфун"'); // создание техстового узла 'ООО "Тайфун"' Node.appendChild(txt); // присвоение узлу <Sender> значение // техстового узла 'ООО "Тайфун"' r.appendChild(Node); // добавление элемента <Sender> в корень // документа как дочернего Node := Doc.createElement ( 'From'); // аналогичные операции для тага <From> txt := Doc.createTextNode( 'http://tayfun.ru/xml/default.asp'); Node.appendChild(txt); r.appendChild(Node); Node := Doc.createElement ( 'To'); // аналогичные операции для тага <To> txt := Doc.createTextNode( 'http://irbis.ru'); Node.appendChild(txt); r.appendChild(Node); Node := Doc.createElement ( 'TypeDocument'); // создание DOMElement (<TypeDocument Id>) Att := Doc.createAttribute ( 'Id ', ' Order'); // создание узла XMLDOMAttribute Node.appendChild(Att); // <TypeDocument Id="Order"/> r.appendChild(Node); end; Следует отметить, что объявление переменной coDoc : CoDomDocument и Doc : DomDocument , а также ее создание методом Create ( Doc:=coDoc.Create;) осуществляется один раз. Объявление переменной находится в секции описания глобальных переменных, а не в локальной процедуре, как было продемонстрировано для наглядности в данном примере (т.е. одна глобальная переменная типа DomDocument на один программный модуль). Результатом работы вышеприведенной программы будет созданный заголовок <Header>, приминительно к нашему примеру xml-документа: изображен на рис. 7. Рис 7. Рис 8. Основное приемущество передачи информации в виде XML-документов в том, что существует возможно формировать сообщение, используя независимые структуры таблиц в СУБД как на принимаемой, так и на передаваемой стороне. Используя наш пример, пусть требуется передать информацию об инвойсах Предприятия А, из СУБД имеющий структуру, изображенную на рис. 6 Для формирования xml-документа, содержащего инвойс первоначально строится SQL-запрос (запрос А) с информацией о самом инвойсе: SELECT * FROM Invoice_General WHERE InvoiceNum = :num // :num - параметр, который задает номер инвойса. и далее строится SQL-запрос (запрос В) информация о товарах, описываемых в инвойсе (детальная спецификация): SELECT Goods,Qulity,Price, HZ_cod FROM Goods WHERE InvoiceNum = :num // :num - параметр, который задает номер инвойса. Ниже представлена часть программы, формирующей тело xml-документа: procedure TThread1.DataBodyCreate(Sender: Tobject); var //coDoc : CoDomDocument ; // объявление сокласса и объекта XMLDomDocument //Doc : DomDocument ; // должно быть глобальным, для всего модуля. r : IXMLDOMElement; // объявление объектов DOMElement Node, Node2 : IXMLDOMElement; // DOMElement; Node3, Node4 : IXMLDOMElement; // txt : IXMLDOMText; // DOMText str : String; // InvoiceNumber: integer; - глобальная переменная - имеет значение 987654 // queryA, queryB : String; - глобальная переменная, имеет значение, соответсвующее запросу // queryA - запрос А генеральная информацией об инвойсе // queryB - запрос B информация о товарах, описываемых в инвойсе (см. текст) begin Query.Close; // закрывает запрос для доступа Query.Text := queryA; // см. по тексту "запрос А" Query.Params[0].AsInteger := InvoiceNumber; // присваивание значения параметров Query.ExecSQL; // выполнение запроса Query.Open; // открытие доступа к данным запроса r:=Doc.Get_documentElement; // получение адреса корневого элемента Node2 := Doc.createElement ( ' Request '); // создание DOMElement (таг <Request>) Node := Doc.createElement ( 'Invoice'); // создание DOMElement (таг <Invoice >) r.appendChild(Node2); // добавление элемента <Request> в корень Node2. appendChild(Node); // добавление элемента <Invoice> в <Request> Node3 := Doc.createElement ( 'Depurture') ; // создание DOMElement (таг <Depurture>) Node. appendChild(Node3); // добавление элемента <Depurture> в <Invoice> str:= Query.FieldByName('Depurture').AsString; // обращение к полю 'Depurture' запроса txt := Doc.createTextNode( str); // создание техстового узла = значению поля Node.appendChild(txt); // присвоение узлу <Invoice> значение // техстового узла, переменной str // аналогичные операции для тага <Destination>, <DataSend>, <DataDepurture>, <Currency> // <DestinationCompany> (поле DB "Consignee" ) Node := Doc.createElement ( 'Destination'); str:= Query.FieldByName('Consignee ').AsString; // имя поля БД может и не совпадать с именем txt := Doc.createTextNode( str); // тага, в этом приемущество использования Node.appendChild(txt); // DOM интерфейса перед СУБД, имеющим // поддержку XML-интерфейса, типа ORACLE 8i ... // или Ms SQL 2000 // формирование запроса на спецификацию по товарам Query.Close; // закрывает запрос для доступа Query.Text := queryВ; // см. по тексту "запрос В", информац. О товарах Query.Params[0].AsInteger := InvoiceNumber; // присваивание значения параметров Query2.ExecSQL; // выполнение запроса Query.Open; // открытие доступа к данным запроса Node3 := Doc.createElement ( ' Imems') ; // создание DOMElement (таг <Imems>) Node. appendChild(Node3); // добавление элемента <Imems> в <Invoice> while not Eof.Query do begin // цикл по всем строкам запроса Node4 := Doc.createElement ( 'Imem'); Node3.appendChild(Node4); // добавление элемента <Imem> в <Imems> str:= Query.FieldByName('Price').AsString; // формирование данных для тага <Price> txt := Doc.createTextNode( str); Node.appendChild(txt); ... // аналогичные операции для тагов <HZ_Cod>, <Quality>, <GoodName> end; end; В результате выполнения данной процедуры формируется следующий текст XML-документа: Для формирования запроса используется метод Open объекта IXMLHttpRequest: procedure Open(const bstrMethod, -тип метода = "POST" bstrUrl, -Url адрес сервера varAsync, -режим связи асинхронный / синхронный = true bstrUser, -имя пользователя для аутентификации bstrPassword) - парольСоздании серверной части обработки документа Как было отмечено ранее, обработка HTTP запроса может осуществляться либо CGI-приложениями, либо Java-сервлетами. Возможен и вариант написания ASP-страниц. Но в этом случае передача данных возможна только методом "GET" через строку запроса. Хотя, обработка HTTP запроса ASP-страниц работает более эффективнее, чем CGI-приложением. Однако, на мой взгляд, без разницы, как обрабатывать, а важнее решить вопрос - как построить программму обработки, а не какими средствами. Если из предыдущей главы мы рассмотрели варианты формирования XML-документ, то задача серверного приложения обратная - разбор XML-документов. Ниже представлена часть программы, осуществляющей разбор xml-документа: procedure Tthread1.DataParser(Sender: Tobject); var r,FNode : IXMLDOMElement; // объявление объектов DOMElement Str,Filename : String; parm : String; CoDocXML, CoDocXSL, CoDocResult : CoDomDocument ; // объявление сокласса и XMLDoc, XSLDoc, ResultDoc : DomDocument ; // объекта XMLDomDocument // HttpStr : String; - глобальная переменная, содержащая строку HTTP запроса Begin XMLDoc:=coDocXML.Create; // создание документа XMLDoc XMLDoc.Set_async(false); // установка синхронного режима обрабработки XMLDoc.LoadXML(HttpStr); // загрузка DOM документа из строки HttpStr r:=Doc.Get_documentElement; // получение адреса корневого элемента FNode:= r.SelectSingleNode("//TypeDocument"); // получение значения элемента <TypeDocument> FileName:= FNode.GetAttibute("id"); // получение значения аттрибута id="Order" FileName:= FileName+".xsl"; // и формирование имени файла Order.xsl XSLDoc:=coDocXSL.Create; // создание документа XSLDoc XSLDoc.Set_async(false); // установка синхронного режима обрабработки XSLDoc.LoadXML(FileName); // загрузка DOM документа из файла Order.xsl ResultDoc:=coDocResult.Create; // создание документа XMLDoc ResultDoc.Set_async(false); // установка синхронного режима обрабработки ResultDoc.validateOnParse := true; // установка проверки разбора XMLDoc.transformNodeToObject(XSLDoc, ResultDoc); // разбор XMLDoc по XSL-шаблону Str:= ResultDoc.text; // переменной Str присваивается текстовое значение // результирующего документа. FNode:= r.SelectSingleNode("//InvoiceNumber"); // поиск элемента <InvoiceNumber> parm:= FNode.text; // и получение значения элемента Query.Close; // закрывает запрос для доступа Query.Text := Str; Query.Params[0].AsString := parm; // присваивание значения параметра Query.ExecSQL; // выполнение запроса end; Вся изюминка разбора заключается в применении XSL-шаблона, который сформирован для каждого типа документа индивидуально. Результатом разбора является строка SQL-запроса. Впоследствие выполнение сформированной строки SQL-запроса осуществит необходимые изменения данных в СУБД. Приимущество использования разбора через щаблон еще и в том, что получается некая гибкость данных, и получается полная независимость работы алгоритма от программного кода. Ниже приведен используемый для обработки документа типа ORDER текст XSL-шаблона: <!-- файл Order.xsl --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <!-- применяем шаблон ко всему документу, начиная с корневого элемента "/" --> <HTML> <xsl:for-each select="//header"> <!-- формирование запроса для записи данных --> <!-- в таблицу регистрации приходящих сообщений TABREG --> INSERT into TABREG ( FROM, TO, TYPEDOC,body) VALUES( ' <xsl:value-of select="from" />' ,' <xsl:value-of select="to" />','<xsl:value-of select="TypeDocument/@id" />' ) </xsl:for-each> <!-- формирование запроса для записи данных в таблицу GOODS --> <!-- информация о товарах --> <xsl:for-each select="//item"> INSERT into GOODS ( invoiceNumber, name, price, quality) VALUES( ' :num', '<xsl:value-of select="name" />' , '<xsl:value-of select="price" />', '<xsl:value-of select="quality" /> ' ) </xsl:for-each> </HTML> </xsl:template> </xsl:stylesheet> Поясняя вышеприведенный пример, надо отметить, что использование пары тагов <HTML> и </HTML> носит формальный характер, т.к. после разбора в результирующем XML-документе формально должен присутствовать хотябы один узел. Метод ResultDoc.text присваивает текстовае значение полученного в ходе разбора XML-документа ResultDoc. В этом случае значением является все то, что обрамлено пары тегов <HTML> и </HTML>, т.е. сформированный нами SQL-запрос. Другой особенностью написания программы надо отметить возможность использования SQL-параметра :num. Использование параметра позволяет упростить текст xsl-шаблона. Определение значение соответствующих элементов узлов XML-документа определякется первоночально выбора по имени соответствующего узла, например: FNode := r.SelectSingleNode(" //InvoiceNumber"); // поиск элемента >InvoiceNumber> и далее использование свойства text: parm := FNode.text; // и получение значения элемента >InvoiceNumber>Коротко об XSL Абревиатура XSL происходит от eXtensible Stylesheet Language - язык форматирования таблиц стилей (XML данных). Как понятно из заголовка eXtensible Stylesheet Language (XSL) используется для форматирования XML данных. По определению W3C XSL состоит из двух частей:
При помощи XSLT мы можем отобрать нужные нам данные из XML файла, и оформить их в виде для предоставления пользователю. Например, в нашем случае мы преобразовали XML данные в виде SQL запроса. Классическое применение XSL - это, как правило форматирование данных в виде HTML страниц или более редкое представление в виде RTF файлов. XSL файл описывает шаблон (template), согласно которому будет совершаться преобразование XML данных. Возращаясь к xsl-шаблонам, в XSLT можно выделить следующие элементы (директивы):
В заключение, необходимо отметить, что использование стандартного XML-парсера msxml.dll является не единственным средством разбора и создания XML-документов. Например, для создание XML документов эффективно использовать компоненты TPageProduser и TТableProduser. Но, данная статья лишь подчеркивает широту и возможность применения на практике DOM модели . Автор будет очень благодарен за отзывы об актуальности темы, общем содержании, стиле изложения, а также всем остальным комментариям, которые помогут в дальнейшем улучшить качество написания сборника статей и выпуску книги, освещающую тему практической стороны использования XML-документов в электронной коммерции. Более подробную информацию о практической стороне применения электронных документов можно почерпнуть на авторском сайте www.eDocs.al.ru Также на авторском сайте планируется разместить исходные тексты и примеры. This is a lengthy text that appears to be an article or chapter on the topic of XML documents, specifically focusing on their use in electronic commerce and data processing. The author provides an overview of the basics of XML documents, including the str Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |