Поиск по этому блогу

вторник, 1 марта 2011 г.

Памятка по MS XML. работа vs msxml.pas

Работа через msxml.pas


создание документа
XMLDOC := CoDOMDocument.Create; // создаем документ
s := '<IMPORT></IMPORT>'; - Root нода
XMLDOC.loadXML(s); // загрузить XML из строки
if Assigned(XMLDOC) then XMLDOC := nil; // освобождаем

Ссылка на root
var Root: IXMLDOMNode;
Root := XMLDOC.documentElement;

Добавляем элемент с артибутом
var
 Root: IXMLDOMNode;
 CurrNode: IXMLDOMNode;
 DataNode: IXMLDOMNode; // CDATA секция
 attr: IXMLDOMAttribute;
 s: WideString;
begin
// Element
 CurrNode := XMLDOC.createElement('VERSION'); //создаем элемент
 // Attribute
 attr := XMLDOC.createAttribute('NAME'); // создаем атрибут
 attr.value := '2.1'; // присваеваем ему значение
 CurrNode.attributes.setNamedItem(attr); // помещаем атрибут в ноду !!!!
 Result.appendChild(CurrNode); // добавляем ноду в XML документ !!!!
end;
или добавляем атрибут

XMLNode := FXMLDocument.selectSingleNode('//ЧегоНадоНайти');
(XMLNode as  IXMLDOMElement).SetAttribute('xmlns', 'NameSpaceКоторыйНадоВставить');


результат
<VERSION NAME="2.1" />

добавляем CDATA SECTION
// Элемент будет содержать CDATA
 CurrNode := XMLDOC.createElement('CONNECTION'); //создаем элемент
 Result.appendChild(CurrNode); // добавляем его в XML документ
 DataNode := XMLDOC.createCDATASection('Это большие данные ... <> !@#$%^&*');
 CurrNode.appendChild(DataNode); // добавляем ноду типа CDATA к текущей

результат
- <CONNECTION>
- <![CDATA[
    Это большие данные ... <> !@#$%^&*
]]>
</CONNECTION>

редактирование CDATA
  CurrNode := TableNode.childNodes.item[0];
  GetData := (CurrNode.childNodes.item[0] as IXMLDOMCDATASection).data;

// CONNECTION  - третья нода от root
  if FConnectionNode = nil then FConnectionNode := Root.childNodes.item[2]; 
  // ветка подчиненная Connection и есть CDATA: соединение
  if (conn <> '') and (FConnectionNode <> nil) then
  begin
    // проверить существует ли такая нода и тип ноды
    if ( FConnectionNode.childNodes.item[0] <> nil ) and (FConnectionNode.childNodes.item[0].nodeType = $00000004)
   then
    CdataNode := FConnectionNode.childNodes.item[0] as IXMLDOMCDATASection;  
    CdataNode.data := conn; //присваеваем данные, которые содержатся в переменной conn типа string



Комментарии
if nodeType = $00000004 проверяет поддерживает ли нода интерфейс IXMLDOMCDATASection, список интерфейсов и их значений можно посмотреть в файле unit msxml.pas
Затем мы обращаемся к ноде в соответствии с интерфейсом  IXMLDOMCDATASection и присваиваем ей значение

редактирование атрибута
 CurrElement := FVersionNode as  IXMLDOMElement; // встаем на ноду к которой принадлежат атрибуты
  // меняем атрибут Name ноды VERSION
  if (verinfo <> '') and (FVersionNode <> nil) then
  CurrElement.setAttribute('NAME', verinfo); // присваиваем атрибуту по имени NAME начение переменной verinfo(string)

******************* ДОСТУП ***************************
доступ к элементу по его номеру
Root := XMLDOC.documentElement;
Root.childNodes.item[3].nodeName = 'FORMATDATA' // вторая от root'а нода

//получить значение атрибута по его имени
<TABLE NAME="org"> </TABLE>
CurrElement := TableNode as  IXMLDOMElement;
TableName := CurrElement.attributes.getNamedItem('NAME').text;
или так
CurrElement := TableNode as IXMLDOMElement;
TableName := CurrElement.getAttribute('NAME');
Результат: org

XML
- <TABLE NAME="ORG" PKNAME="KODORG" FKNAME="пусто" KEYWORD="ОРГАНИЗАЦИИ">
...
</TABLE>
Поиск
function TfrmXMLTree.FindTableByName(TableName: WideString): IXMLDOMNode;
var
 QueryStr: WideString;
begin
 QueryStr := '//TABLE [@NAME=' + QuotedStr(TableName) + ']'; ;
 Result := XMLDOC.selectSingleNode(QueryStr);
end;
// вызываем
FindTableByName('ORG') // это и есть имя таблицы, которую нам надо найти
QueryStr - текст запроса
//TABLE - наименование элемента
@NAME - наименование атрибута
TableName - имя таблицы, которую нам надо найти

Простой рекурсивный обход XML дерева (без обхода атрибутов)
// обходим XML схему
procedure Parsing_Prepare; // подготовка парсинга создаем параметры
var
 root: IXMLDOMNode;
 ChildNodes: IXMLDOMNodeList;
// рекурсивная процедура
 procedure RecurceGetNode(XMLNode: IXMLDOMNode);
 var
  i: integer;
  CurrNodeName: string;
  CurrElement: IXMLDOMElement;
 begin
  if XMLNode = nil then exit;
  CurrNodeName := '';
  CurrNodeName := XMLNode.nodeName; // получаем имя ноды
  ShowMessage(CurrNodeName); //... сообщаем ее
// цикл для обхода
  for i := 0 to XMLNode.childNodes.length - 1 do
    begin
      RecurceGetNode(XMLNode.childNodes.item[i]);
    end;  // for
 end;
// тело
begin
 root := XMLDoc1.documentElement; // ссылка на root ноду
 RecurceGetNode(root); // запускаем рекурсивную функцию от root
end;

Импорт ноды XML 6.0


XMLNode := FXMLDocument_tmp.ImportNode(FXMLDocument.selectSingleNode('//ИмяЭлемента'),true);
FXMLDocument_tmp.DocumentElement.AppendChild(XMLNode);
FXMLDocument_tmp.save('new_tmp.xml');

{ Импорт с подчиненными
XMLNode := FXMLDocument_tmp.ImportNode(FXMLDocument.DocumentElement.FirstChild,true);