На примере, обьяснен общий принцип работы с XML в TestComplete (DelphiScript).

Для понимания XML советую предварительно просмотреть:
ru.wikipedia.org/wiki/XML - короткая и понятная статья по XML
www.w3schools.com/xml/ - руководство по XML

К примеру есть XML файл (сохранен по адресу ‘C:\Test.xml’):






Из него необходимо получить значение атрибутов Login, Password, Role.

Для этого необходимо выгрузить XML-файл в объект, понятный для среды разработки, который можно обрабатывать в скрипте.
TestComplete позволяет работать с любыми XML, используя DOM XML (msdn.microsoft.com/ru-ru/library/2bcctyt8.aspx - XML документы и данные).

Пример: Функция загружает указанный XML файл, если структура XML нарушена - выдает сообщение об ошибке XML-парсера, в результате работы функция возвращает объект.

function InitializeXML(APath: WideString): OleVariant;
var File: OleVariant;
 Doc: OleVariant;
 s: OleVariant;
begin
 File := APath;
 Doc := Sys.OleObject('Msxml2.DOMDocument.6.0');
 Doc.async := false;
 Doc.load(File);
 if Doc.parseError.errorCode <> 0 then
  begin
   s := 'Reason:' + #9 + Doc.parseError.reason + #13#10 +
   'Line:' + #9 + VarToStr(Doc.parseError.line) + #13#10 +
   'Pos:' + #9 + VarToStr(Doc.parseError.linePos) + #13#10 +
   'Source:' + #9 + Doc.parseError.srcText;
   Log.Error('Cannot parse the document.', s);
   Exit;
   end;
 Result := Doc;
end;

Для получения данных из XML используем средства DOM XML и XPath.
Для этого необходимо у объекта XML-документа (либо объекта XML-ноды), вызвать функцию selectNodes(), и передать в функцию XPath-запрос.
Пример:

XMLDoc.selectNodes('//User')

Функция selectNodes - возвращает коллекцию объектов, т.е. если даже результат запроса всего одна запись, возвращается коллекция с одним объектом. НЕЛЬЗЯ прямо обращаться к нодам атрибутам, полученным из selectNodes. т.е. выражение XMLDoc.selectNodes('//User').getAttribute('Login') - ошибочно. Правильно будет XMLDoc.selectNodes('//User').item(0).getAttribute('Login');
Чтобы узнать количество элементов (item) коллекции необходимо вызвать свойство length.
Пример: XMLDoc.selectNodes('//User').length - возвращает количество нод User в XML документе.
Для обработки всех элементов коллекции, необходимо пробежаться по каждому из них обращаясь по индексу элемента, причем обработку необходимо проводить в соответствии с возвращаемым типом данных (ноды, атрибуты, текст)

Пример: Получение данных

procedure TestDOMXML();
var XMLDoc: OleVariant;
 i: Integer;
 User: WideString;
 Password: WideString;
 Role: WideString;
begin
 XMLDoc := InitializeXML('C:\Test.xml');
 for i:=0 to XMLDoc.selectNodes('//User').length-1 do
  begin
   User:= XMLDoc.selectNodes('//User/@Login').item(i).text;
   Password:= XMLDoc.selectNodes('//User/@Password').item(i).text;
   Role:= XMLDoc.selectNodes('//User/@Role').item(i).text;
   Log.Message('User: ' + User + ' Password: ' + Password + ' Role: ' + Role);
  end;
end;

возможен другой вариант цикла обработки
for i:=0 to XMLDoc.selectNodes('//User').length-1 do
  begin
   User:= XMLDoc.selectNodes('//User').item(i).getAttribute('Login').text;
   Password:= XMLDoc.selectNodes('//User').item(i).getAttribute('Login').text;
   Role:= XMLDoc.selectNodes('//User').item(i).getAttribute('Login').text;
   Log.Message('User: ' + User + ' Password: ' + Password + ' Role: ' + Role);
  end;

XPath - выражение //User/@Login - выбирает из XML все ноды User, у каждой из них выбирает указанный атрибут (Login, Password, Role). Если запрошенного атрибута нет, то возвращается Null (или если привести к строке '0')

Если есть задача получить ноды, или получить значение атрибута ноды определенного типа, условия фильтрации удобно вмещать в выражение XPath:
Пример: Получить логины пользователей, которые являются администраторами:

//User[@Role='Administrator']/@Login

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

Нравится

Поделиться

2 комментария

привет, твоя статья мне очень помогла:) А есть пример как добавлять инфу в хмл? иль хоть линка где рпо это почитать?:)

советую обращаться к первоисточникам MSDN

Показать все комментарии
Публикация

Что такое XPath?

XPath - это синтаксисдля адресации частей XML-документа

XPath - использует пути для адресации элементов XML

XPath - является важнейшей частью стандарта XSLT

XPath - не является XML-форматом

XPath - является стандартом W3C

 

XPath - использует адресные выражения для идентификации узлов в XML-документе. Эти адресные выражения очень похожи на выражения, с которыми вы сталкиваетесь при работе с файловой системой компьютера:

w3schools/xpath/default.asp

 Пример XPath

Empire Burlesque Bob Dylan USA Columbia 10.90 1985 Hide your heart Bonnie Tyler UK CBS Records 9.90 1988 /year>

Это выражение XPath:

catalog/cd/price

определяет элементы price, дочерние относительно элементов cd, подэлементов элемента catalog

Пути адресации XPath

Выражения для Путей Адресации

Имя

Описание

Пример

Результат

/

Дочерний элемент узла

/price

элемент price

//

Узел и его дочерние элементы

//cd

элемент cd и его подэлементы

|

список дочерних элементов

price | title

элемент price и title

Оси

Оси служат для определения набора узлов относительно данного узла.

Имя

Описание

Узел

self

сам узел

 

child

Дочерние узлы

 

parent

Родительский узел

 

descendant

Потомки узла

 

descendant-or-self

Узел и его потомки

 

ancestor

Предки узла

 

ancestor-or-self

Сам узел и его предки

 

following

Все узлы после данного

 

following-sibling

Все узлы этого же уровня после данного

 

preceding

Все узлы перед данным

 

preceding-sibling

Все узлы этого же уровня перед данным

 

attribute

Узлы аттрибутов

 

namespace

Узлы пространства имен

 

 

Предикаты Путей Адресации

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

Предикаты записываются внутри квадратных скобок.

Например, child::price[price=9.90] возвращает множество узлов, где элемент price имеет значение 9.90.

Новое множество узлов содержит все узлы, для которых значение предиката верно.

Сокращения для Путей Адресации

При описании путей адресации могут использоваться сокращения.

Сокращение

Значение

 

child::

@

attribute::

.

self::

..

parent::

//

/descendant-or-self/

число

[position()='значение']

Выражения XPath

Числовые Выражения

Числовые выражения используются для выполнения арифметических операций над числами.

Оператор

Описание

Пример

Результат

+

Сложение

6 + 4

10

-

Вычитание

6 - 4

2

*

Умножение

6 * 4

24

div

Деление

8 div 4

2

mod

Остаток от деления

5 mod 2

1

Замечание: XPath всегда преобразует аргумент в число перед выполнением арифметических операций.

Операции равенства

Операции равенства используются для проверки равенства двух значений.

Оператор

Описание

Пример

Результат

=

Равно

price=9.80

'истина' (если значение price равно 9.80)

!=

Не равно

price!=9.80

'ложь'

 

Проверка по Множеству Узлов

В случае, когда тестовое значение проверяется на равенство по множеству узлов, результатом будет 'истина', если множество узлов содержит какой-либо узел со значением, которое соответствует тестовому значению.

Когда тестовое значение проверяется на неравенство по множеству узлов, результатом будет 'истина', если множество узлов содержит хотя бы один узел со значением, отличным от тестового.

В итоге множество узлов может быть равно и не равно одновременно!!!

Операции Сравнения

Эти операции используются для сравнения двух значений.

Оператор

Описание

Пример

Результат

 

Меньше

price9.80

'ложь' (если price равно 9.80)

=

Меньше или равно

price=9.80

'истина'

Больше

price>9.80

'ложь'

>=

Меньше или равно

price>=9.80

'истина'

Замечание: XPath всегда преобразует каждый аргумент в число перед выполнением сравнения.

Булевы Выражения

Оператор

Описание

Пример

Результат

or

или

price=9.80 or price=9.70

'истина' (если price равно 9.80)

and

и

price=9.80 and price=9.70

 

 

Функции XPath

Библиотека Функций XPath

Библиотека функций XPath включает набор базовых функций для преобразования данных.

Числовые Функции

Имя

Описание

Пример

Результат

round

Округляет до ближайшего целого.

round(3.14)

3

ceiling

Округляет до ближайшего целого, которое больше данного.

ceiling(3.14)

4

floor

Округляет до ближайшего целого, которое меньше данного.

floor(3.14)

3

count

Возвращает количество узлов.

count(nodeset)

количество узлов в множестве узлов

number

Преобразует аргумент в число.

number(price)

Численное значение элемента price

sum

Возвращает сумму списка чисел.

sum(/cd/price)

Суммарная цена всех CD

 

Строковые Функции

Имя

Описание

Пример

Результат

string

Преобразует аргумент в строку.

string(3.14)

'3,14'

string-length

Возвращает длину строки.

string-lenght('Beatles')

7

substring

Возвращает подстроку.

substring('Beatles',1,4)

'Beat'

substring-after

Возвращает остаток строки после второго аргумента.

substring-after('12:30',':')

'30'

substring-before

Возвращает часть строки перед вторым аргументом.

substring-before('12:30',':')

'12'

contains

Возвращает 'истину', если первая строка содержит вторую.

contains('XML','X')

'истина'

starts-with

Возвращает 'истину', если первая строка начинается второй.

starts-with('XML','X')

'истина'

concat

Возвращает конкатенацию двух строк.

concat('The',' ','Beatles')

'The Beatles'

normalize-space

Удаляет лишние пробелы в строке.

normalize-space('  The    Beatles')

'The Beatles'

translate

Заменяет символы в строке.

translate('12:30',':','.')

'12.30'

 

Булевы Функции

Имя

Описание

Пример

Результат

boolean

Преобразует аргумент к булевому типу.

boolean(3.14)

'истина', если price не равен нулю

false

Вовращает 'ложь'.

number(false())

0

true

Возвращает 'истину'.

number(true())

1

not

Возвращает отрицание.

not(false())

'истина'

Источник: www.w3schools.com/XPath/default.asp

Нравится

Поделиться

0 комментариев
Показать все комментарии

Здравствуйте!

Неоднократно пользователям приходится работать с сервисами выгруженными в *xml.
Привожу небольшой список редакторов для работы с данным форматом.

1) Для просмотра скриптов - XMLNotepad (официальный продукт Microsoft);
2) Для редактирования - Notepad (после редактирования сохраняет файл, после чего его можна загрузить в Terrasoft Administrator, т.к. другие редакторы меняют *.xml)
3) Для работы (редактирования и просмотра) - Altova;
www.altova.com/simpledownload2.html?gclid=CNzj9r6-nZgCFYoH3godyWtRnA
www.altova.com/products/xmlspy/xml_editor.html
4) Для сравнивания сервисов в проектах (с доработками конфигурации) - Araxis.

Поделитесь, возможно, Вы используете другое ПО для данных целей?!

Нравится

Поделиться

5 комментариев

Для меня незаменимым инструментом является VIM (vimdiff в комплекте) + FAR

Продвинутый редактор — кошмар для случайного пользователя. Если его удается в конце-концов закрыть, то вздыхаешь с облегчением и твердой уверенностью, что больше не будешь запускать эту программу ни в коем случае.
Действительно, такой редактор нельзя просто открыть и начать работать — требуется предварительная подготовка. Зато стоит раз испытать его в работе, и поражаешься, как мог обходиться без него раньше.
http://ru.wikibooks.org/wiki/Vim

Из графических, нравиться: Notepad++

С редактированием XML так же неплохо справляется Microsoft Visual Studio, наверняка он стоит, как минимум для отладки :)

Для отладки - Microsoft Visual Studio :-)

Может немного не в тему, но все жу :)
Сталкивался с задачами открытия больших xml - файлов (100mb+). Быстрее всех парсит:
1)XMLNotepad (официальный продукт Microsoft); - около минуты(вероятно SAX).
в то время как Visual Studio, NotePad и еще несколько редакторов(названия уже не вспомню) загибаются наглухо.

Использую для работы XMLMarker версии 1.1(free soft) для работы с небольшими файлами меня вполне устраивает, контролирует синтаксис, имеет три окна отображения информации из файла
-Дерево(в этом окне удобно осуществлять навигацию);
-Текстовый файл(где осуществляется редактирование, подсвечивается узел, на котором находиться курсор);
-Таблица(табличное представление узла, на котором установлен курсор с показом атрибутов).
XMLNotepad - не понравился после XMLMarker.
P.S. Сейчас не могу сбросить ссылку на проект, нет под рукой... постараюсь не забыть.

Показать все комментарии

В процессе моей работы иногда возникает ситуация, когда необходимо передать настроенную в TerrasoftCRM интеграцию, пользовательский запрос либо другие данные. Можно делать это разными способами, но хотелось иметь под рукой инструмент, с помощью которого можно быстро выгрузить данные из одной базы и загрузить в другой. Помимо этого, хотелось бы иметь возможность просто поменять содержимое перед загрузкой и не быть зависимым от конкретной СУБД.
Я реализовал небольшую утилиту в конфигурации TerrasoftCRM, которая позволяет выгрузить наполнение из выбранных таблиц и загрузить его на другой базе.
На примере ее реализации можно посмотреть как организована работа с объектом XMLStorage. На текущий момент она очень проста - выгружает все данные из выбранных таблиц и сохраняет все это в XML-файл. В будущем я планирую сделать возможность фильтрации выгружаемых данных, "умную" обработку полей, которые являются внешними ключами и прочее.

Нравится

Поделиться

3 комментария

Костя! Спасибо!
Сэкономил мне время на модуль для СВТ :)

Всегда пожалуйста, Евгений!

Спасибо, Костя! Я тоже уже заюзал пару функций из DataManager-а, что очень облегчило мою задачу.

Показать все комментарии

Пример по subj

var Dataset = Services.GetNewItemByUSI('ds_Contact');
Dataset.Open();

var Stream = new ActiveXObject('ADODB.Stream');
Stream.Type = 1;
Stream.Mode = 3;
Stream.Open();

Dataset.SaveToXML(Stream);
Dataset.Close();

Stream.SaveToFile('D:\\Data.xml');
Stream.Close();

Нравится

Поделиться

0 комментариев
Показать все комментарии

Добрый день! Нашел в SDK скрипт по работе с xml файлом.
Имеется xml файл (client.xml), который имеет следующий вид:

xml version="1.0" encoding="Windows-1251"?>
records>
        record>
               
                fio>Иванов Иванfio>
                company>Старcompany>
                position>Начальник отделаposition>
                tel>7777777tel>
                email>ivan@gmail.comemail>
                country>Ukrainecountry>
                city>Kievcity>
                address>Пушкина, 10address>
                note>note>
        record>
records>

Создав простое окно (от родителя BaseGridArea) вызываю его планировщиком windows, повесив на событие OnPrepare след. скрипт,взятый с SDK пытаюсь получить значения fio, company...., и на событие OnShow скрипт закрытия окна - так как это было уже описано на форуме:

function wnd_UrlOnPrepare(Window) {
var Storage = new ActiveXObject('TSObjectLibrary.XMLStorage');
var StorageNode = new ActiveXObject('TSObjectLibrary.XMLStorageNode');

// Объект хранения представления дерева узлов в текстовом виде
var Value   = new ActiveXObject('TSObjectLibrary.Value');
Value.Value = new ActiveXObject('TSObjectLibrary.StringsList');

        // Файл для загрузки XML-данных (необходимо наличие корректного XML-файла
        // по указанному адресу)
        var FileName = 'C:\client.xml';

        // Загрузка XML-данных из файла
        Storage.LoadFromFile(FileName);

        // Вывод текста XML
        //var MessageString = Storage.Text;
        //ShowMessage("Загруженный XML-файл:\n " + MessageString);

        // Корневой узел
        StorageNode = Storage.RootNode;

        // Построение дерева для загруженого XML-документа
        BuildTree(-1, StorageNode, Value);

        // Вывод дерева узлов XML
        //MessageString = Value.Value.Text;
        //ShowMessage("Вывод дерева узлов:\n " + MessageString);

    //-----------------------------------------------------------------------------
// Применение методов интерфейса IXMLStorageNode.
//-----------------------------------------------------------------------------

var record = StorageNode.GetChildNode('record');
var fio = StorageNode.GetChildNode('record').GetChildNode('fio');
var company = StorageNode.GetChildNode('record').GetChildNode('company');
var position = StorageNode.GetChildNode('record').GetChildNode('position');
var tel = StorageNode.GetChildNode('record').GetChildNode('tel');
var email = StorageNode.GetChildNode('record').GetChildNode('email');
var country = StorageNode.GetChildNode('record').GetChildNode('country');
var city = StorageNode.GetChildNode('record').GetChildNode('city');
var address = StorageNode.GetChildNode('record').GetChildNode('address');

// В след. строке пытаюсь получить значение fio
var fioValue = StorageNode.GetChildNode('record').GetChildNode('fio').Text;
}

// Функция вывода сообщения
function ShowMessage(Str) {
    for (var i = 1; i arguments.length; i++ ) {
        Str = Str.replace(new RegExp('%' + i), arguments[i]);
    }
   // WScript.Echo(Str);
   ShowInformationDialog(Str);
}

// Функция рекурсивного построение дерева узлов
function BuildTree(Level, Item, Value) {

        // Строка для хранения конечного результата
        var TotalString = new String();

        // Строка выравнивания позиций узлов по ширине нижних уровней
        var WidthString = new String();

        // Переход на уровень вниз
        Level++;

        // Создание текущей глубины обхода для текстового представления,
        //если она не была достигнута
        if (Level >= Value.Value.Count) {
                Value.Value.Add('');
        }
        // Cчитывание строки структуры уровня для добавления узлов
        // того же уровня
        TotalString = Value.Value.Items(Level);

        // Выравнивание узла верхнего уровня по ширине нижних узлов.
        for (var k = Level + 1; k Value.Value.Count; k++) {
                WidthString = Value.Value.Items(k);
                while (TotalString.length WidthString.length) {
                        TotalString += '_';
                }
        }

        // Добавление элемента в текстовое представление
        TotalString = TotalString + '' + Item.Name + '>';
        Value.Value.Items(Level) = TotalString;

        // Рекурсивный вызов построения дерева для всех дочерних узлов
        for (var i = 0; i Item.Count; i++) {
                BuildTree(Level, Item.Items(i), Value);
        }
        // Переход на уровень вверх в дереве после завершения обхода
        // текущего узла
        Level--;

        // Вывод сообщения о завершении обхода дерева
        if (Level 0) {
                ShowMessage("Обход дерева узлов завершен.");
        }
}

Но не получается вытянуть само значение, которое расположено между скобками, т.к. код var fioValue = StorageNode.GetChildNode('record').GetChildNode('fio').Text;
выводит все полностью, еще и с неправильной кодировкой:

 
"Парашута Александр

Подскажите пожалуйста с помощью какого метода можно корректно вытянуть значения параметров fio, company...
Еще вопрос по поводу закрытия вызываемого окна, в скрипте
function wnd_UrlOnShow(Window) {
     Self.Close();
}

Выдает ошибку:
TSDskWindowLibrary.DskWindow: Cannot change Visible in OnShow or OnHide

Заранее спасибо!

Нравится

4 комментария

Добрый день, Сергей!

Обратите, пожалуйста, внимание на текущую версию примера для работы с XML тут: http://terrasoft.com.ua/sdk/ пример IXMLStorageExample.js
Пример существенно отличается от представленного выше.

Кстати, в представленном файле client.xml ошибка в строке с телефоном - пропущен символ "<"

Насчет корректного вытягивания значений - рекомендуется использовать функции SetAttributeAsStr() и GetAttributeAsStr(), а с помощью прямого обращения к ноде нужный текст получить не удалось.
Желаю успехов!

Добрый день! Так я именно с IXMLStorageExample.js и взял код, только у меня нет той части в которой создаются новые аттрибуты, т.к. они мне не нужны, пропущенный символ вставил(нечаянно стер когда рисовал семерки :) ), насчет функций SetAttributeAsStr() и GetAttributeAsStr() - так они же для вытягивания аттрибутов, т.е. тех данных которые находятся непосредственно внутри скобок, например для записи

<record tel=77777777> 

аттрибутом является tel, но у меня запись вида

<tel>7777777<tel> 

:(

P.S> а что насчет ошибки с закрытием окна?
Спасибо! :)

Нашел решение! Привожу пример, может кому-то еще понадобиться извлечь данные из xml:

var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
function loadXML(xmlFile)
{
  xmlDoc.async="false";
  xmlDoc.onreadystatechange=verify;
  xmlDoc.load(xmlFile);
  xmlObj=xmlDoc.documentElement;
}
 
function verify()
{
  // 0 Object is not initialized
  // 1 Loading object is loading data
  // 2 Loaded object has loaded data
  // 3 Data from object can be worked with
  // 4 Object completely initialized
  if (xmlDoc.readyState != 4)
  {
      return false;
  }
}
loadXML('C:\client2.xml');
 
var fio = xmlObj.childNodes(0).childNodes(0).firstChild.text;
var company = xmlObj.childNodes(0).childNodes(1).firstChild.text;
var position = xmlObj.childNodes(0).childNodes(2).firstChild.text;
var tel = xmlObj.childNodes(0).childNodes(3).firstChild.text;
var email = xmlObj.childNodes(0).childNodes(4).firstChild.text;
var country = xmlObj.childNodes(0).childNodes(5).firstChild.text;
var city = xmlObj.childNodes(0).childNodes(6).firstChild.text;
var address = xmlObj.childNodes(0).childNodes(7).firstChild.text;

более подробно можно почитать тут: http://www.codetoad.com/xml_javascripti_tutorial.asp

P.S> С закрытием окна так и не разобрался :(
все равно выдает ошибку..

Рад что требуемое решение найдено.
Про закрытие окна описано тут: http://community.terrasoft.ua/forum/topic/1989#comment-6640
Желаю успехов!

Показать все комментарии

Здравствуйте!
Есть необходимость в конце каждого дня собирать введенные за текущий день данные в xml-файл и экспортировать это. Можно ли создать такой xml-файл, чтоб потом новые данные таким образом импортировать в другую базу? Скажите, пожалуйста, есть ли такая возможность?

Нравится

4 комментария

Можно. Используйте XMLStorage (см. www.terrasoft.ua/sdk) для создания такого файла.
И
1. Средства другой базы для импорта такого файла
2. Тот же XMLStorage для распарсивания файла и экспорта в другую базу стандартными средствами (Например через ADODataset).

Здравствуйте!
Еще есть вариант воспользоваться методом IDBDataset.SaveToFile(см. http://www.terrasoft.ua/sdk/)

Спасибо!
А как это использовать? Где-то в скрипте прописывать, а в разделе кнопочку добалять?

Добрый день, Екатерина.

В Вашем случае наиболее подходящий вариант - использование объекта XMLStorage.
Использовать метод IDBDataset.SaveToFile() в Вашем случае неудобно - данные сохраняются в бинарном виде, непригодном для дальнейшей обработки.
Подробный пример на JScript по созданию и использованию XMLStorage доступен тут: www.terrasoft.ua/sdk, нужно искать описание интерфейса IXMLStorage. Пример достаточно полный, внимательное изучение его позволит Вам легко реализовать Вашу задачу.
Запускать выгрузку лучше по действию (т.е. пункту меню, в обработчике OnExecute котогоро вызывать Вашу функцию по выгрузке данных в xml).
Желаю успехов!

Показать все комментарии