Доброго дня, имеется bpm которая при GET запросе 0/ServiceModel/EntityDataService.svc/ContactColletion возвращает xml с контактами, можно ли GET запросом возвращать JSON и если да, то где про это написанно? Если нельзя, то как вернуть JSON для oData 3?

Нравится

3 комментария
Лучший ответ

Добавьте header к запросу

Accept: application/json;odata=verbose

Добавьте header к запросу

Accept: application/json;odata=verbose

я смог сделать это в постмане, но все же не понятно, мб подскажете возможно ли в террасофте возвращать json по обращению к uri, если можно сделать это не переписывая сервис, буду благодарен за подсказку)
условно я иду по адресу /0/ServiceModel/EntityDataService.svc/ContactCollection и мне падает 
 

{

    "d": {

        "results": [

            {

                "__metadata": {

                    "id": "http://localhost:85/0/ServiceModel/EntityDataService.svc/ContactCollect…",

                    "uri": "http://localhost:85/0/ServiceModel/EntityDataService.svc/ContactCollect…",

                    "type": "Terrasoft.Configuration.Contact"

                },

                "Photo": {

                    "__deferred": {

                        "uri": "http://localhost:85/0/ServiceModel/EntityDataService.svc/ContactCollect…"

                    }

                },

                "Owner": {

                    "__deferred": {

                        "uri": "http://localhost:85/0/ServiceModel/EntityDataService.svc/ContactCollect…"

                    }
...и т.д.

Насколько понял, только заголовком. Такой формат здесь не поддерживается: «ContactCollection?$format=json». А в OData 4 по умолчанию идёт JSON.

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

На клиенте нужно вставить запись в некоторую таблицу, одним из значений параметров есть Id записи контакта, его нужно получить из таблицы Contact запросом.

Например, вот так:

            setLoggerActivatorParameter: function(clinic) {
                var loggerActivatedById;
                if (this.Ext.isEmpty(clinic)) {
                    return loggerActivatedById;
                }
                var esqContact = Ext.create("Terrasoft.EntitySchemaQuery", {
                    rootSchemaName: "Contact"
                });
                var esqAccountFilter = esqContact.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                    "Account", clinic.value);
                var esqDataLoggerActivatorFilter =
                    esqContact.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                    "DataLoggerActivator", true);
                esqContact.filters.add("esqAccountFilter", esqAccountFilter);
                esqContact.filters.add("esqDataLoggerActivatorFilter", esqDataLoggerActivatorFilter);
                esqContact.getEntityCollection(function(result) {
                    if (result.success && result.collection.getCount()) {
                        loggerActivatedById = result.collection.first().get("Id");
                        return loggerActivatedById;
                    }
                }, this);
            }

Но из-за ассинхроности, пока отработает функция setLoggerActivatorParameter, то запись уже добавится в таблицу без значения поля loggerActivatedById.

Вопрос в том, каким образом можно реализовать такую функциональность, чтобы получать значение поля loggerActivatedById до того, как будет добавлена новая запись в таблицу.

Интересно также, есть ли другие варианты решения данной задачи, кроме запуска процесса, в котором будет реализована данная функциональность.

Нравится

1 комментарий

Из других вариантов:

1) сервис

2) использовать chain на клиенте (реализация гуглится по форуму или тут)

3) кривой, но рабочий (более-менее) способ — делать тот же самый esq только при загрузке страницы, где-нибудь в init-е. Ну и складировать результат в переменную. Потом в обработчике уже к переменной обращаться.

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

На примере, обьяснен общий принцип работы с 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

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

Добрый день! Нашел в 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() - так они же для вытягивания аттрибутов, т.е. тех данных которые находятся непосредственно внутри скобок, например для записи

 

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

7777777 

:(

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
Желаю успехов!

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