Загрузка и анализ документа XML.

Обмен информацией в формате XML - это чрезвычайно удобный механизм, позволяющий свести к минимуму проблемы внутрифирменных форматов данных. Эти проблемы сводятся к сложностям при обмене информацией с контрагентами фирмы. Зачастую проблема стоит не только в невозможности других воспринимать предлагаемый вами формат (DBF, ASCII и т.п.), сколько в нежелании приспосабливаться к ним. Эти форматы не очень удобны. К тому же у вашего партнера наверняка уже есть наработки в этой области. Так почему бы вам не приспособится к его формату обмена данными?

Язык XML позволяет разрабатывать форматы описания данных, которые могут стать тем мостиком, котрый свяжет всех контрагентов и устранит технические и психологические барьеры, неизбежно возникающие при приспособлении к чужим технологиям.

Технология XML тоже не назовешь родной, однако ее возможности и универсальность при описании текстовых данных перекрывают все сложности, связанные с ее освоением.

Формировать документы в формате XML достаточно просто. Следует лишь познакомится с конкретным DTD и образцами корректных документов. А вот загрузка может быть достаточно трудна, если не прибегать к помощи готовых решений в виде XML парсеров. Их довольно много для разных платформ и при желании можно найти их описания в WWW. Одним из наиболее распространенным на платформе Windows является Microsoft XML Parser. Дело в том, что он входит в состав Microsoft Explorer 5.0 и более позние версии. Он доступен в виде объекта ActiveX. Данный парсер является верифицирующим, то есть проверяет не только синтаксическую проверку документа, но и семантическую корректность в соответствии с заданным DTD.

Для загрузки и анализа документа в Delphi рассмотрим следующий код.

{Вспомогательная функция. Формирует текст сообщения об ошибке 
 
 Вход   : Error: TXMLDOMParseError 
 Выход  : Отчет об ошибке } 
function getParseError(Error: Variant): string; 
begin 
  Result :=  'Ошибка при загрузке документа ["' + Error.url + ' ]'#13#10 
             + Error.reason + #13#10#13#10; 
 
  if (Error.line > 0) then 
    Result := Result + 'строка ' + Error.line + ', символ ' + error.linepos + #13#10 
                     + Error.srcText; 
end; 
 
 
 
{Загружает файл в Microsoft.XMLDOM. Строит дерево DOM в TreeView 
 
 Вход   : Имя файла XML} 
procedure TfImport.LoadOnixDoc(const FileName: string); 
var 
  XML, parseError: variant; 
  Node, mainNode, childNodes: variant; 
  i: integer; 
  TreeNode: TTreeNode; 
 
  { рекурсивно обходит дерево элементов и заполняет TreeView } 
  procedure LoadItems(TreeNode: TTreeNode; Node: variant); 
  var i: integer; 
  begin 
    TreeNode := TV.Items.AddChild(TreeNode, Node.nodeName); 
    TreeNode.ImageIndex := TreeNode.Level; 
    TreeNode.SelectedIndex := TreeNode.ImageIndex; 
    if Node.nodeName = '#text' then 
    begin 
      TreeNode.Text := Node.nodeValue; 
      TV.SetNodeBoldState(TreeNode, true); 
    end; 
    for i:=0 to Node.childNodes.length-1 do 
      LoadItems(TreeNode, Node.childNodes.item[i]); 
 
  end; 
begin 
  XML := CreateOleObject('Microsoft.XMLDOM'); 
 
  // async 
  // Свойство, доступное для записи и чтения, 
  // идентифицирующее текущий режим обработки (синхронный или асинхронный) 
  XML.Async := false; 
 
  // load(url) 
  // Загружает документ, адрес которого задан параметром url. 
  // В случае успеха возвращает логическое значение true. Необходимо иметь в виду, 
  // что вызов этого метода сразу же обнуляет содержимое текущего документа 
  XML.load(FileName); 
 
  // Можно загружать из строки: 
  // loadXML(xmlString) 
  // Загружает XML - фрагмент, определенный в передаваемой строке 
 
  // parseError 
  // Возвращает ссылку на объект XMLDOMParseError, при помощи которого 
  // можно получить всю необходимую информацию о последней ошибке анализатора. Только для чтения. 
  if XML.parseError.errorCode <> 0 then 
  begin 
    ShowMessage( getParseError(XML.parseError) ); 
  end else 
  begin 
 
    mainNode := XML.documentElement; 
 
    { Загрузка DOM в TreeView } 
    LoadItems(nil, mainNode); 
    // дерево DOM построено в TreeView 
 
 
    TreeNode := TV.Items[1]; 
    while Assigned(TreeNode) do 
    begin 
      TreeNode.Expand(false); 
      TreeNode := TreeNode.GetNextSibling; 
    end; 
    if Assigned(TV.Items[0]) then TV.Items[0].Expand(false); 
 
  end; 
end; 





Пример документа XML Onix.

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE ONIXMessage SYSTEM "onix-international.dtd">

<ONIXMessage release="1.1">

	<FromCompany>ТД Библио-Глобус</FromCompany>
	<FromPerson>Kirillov Alexey kirillov@biblio-globus.u</FromPerson>
	<ToCompany>EDItEUR</ToCompany>
	<ToPerson>EDItEUR chief manager</ToPerson>
	<MessageNumber>1</MessageNumber>
	<SentDate>23.12.00</SentDate>
	<DefaultLanguageOfText>rus</DefaultLanguageOfText>
	<Product>
		<RecordReference>247825</RecordReference>
		<NotificationType>3</NotificationType>
		<ISBN>966-7393-05-4</ISBN>
		<ProductForm>BB</ProductForm>
		<DistinctiveTitle>SQL энциклопедия пользователя</DistinctiveTitle>
		<Contributor>
			<ContributorSequenceNumber>0</ContributorSequenceNumber>
			<ContributorRole>A01</ContributorRole>
			<PersonName>Х. Ладани</PersonName>
			<PersonNameInverted>Ладани, Х.</PersonNameInverted>
			<BiographicalNote>Книга раскрывает темы, которые часто
			 не описываются или достаточно кратко представлены в
			 руководствах пользователя
			 - подзапросы, структуры данных, представления, 
			 производительность, целостность и защита данных.
			</BiographicalNote>
		</Contributor>
		<NumberOfPages>624</NumberOfPages>
		<ImprintName>ДиаСофт</ImprintName>
		<MediaFile>
			<MediaFileTypeCode>04</MediaFileTypeCode>
			<MediaFileFormatCode>03</MediaFileFormatCode>
			<MediaFileLinkTypeCode>06</MediaFileLinkTypeCode>
			<MediaFileLink>
			http://shop.biblio-globus.ru/photos1/05/58983.jpg
			</MediaFileLink>
		</MediaFile>
		<SupplyDetail>
			<SupplierName></SupplierName>
			<AvailabilityCode></AvailabilityCode>
			<Price>
				<PriceTypeCode>01</PriceTypeCode>
				<PriceAmount>425</PriceAmount>
				<CurrencyCode>RUB</CurrencyCode>
			</Price>
		</SupplyDetail>
	</Product>

</ONIXMessage>




Для работы Вам понадобятся файлы DTD: ONIX INTERNATIONAL DTD





В итоге мы сформируем следующее дерево документа:

Демонстрационный пример с исходным текстом на Delphi вы можете скачать здесь: PlayingWithXML.zip.

составление статьи: Андрей Чудин, ЦПР ТД Библио-Глобус.