:: Visual Foxpro, Foxpro for DOS
как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Уважаемые знатоки. Прошу мне помочь в решении одной задачи.
есть веб сервис по POST запросу -который возвращает данные в формате JSON и эти данные необходимо записать в таблицу dbf
возможно этот вопрос обсуждался и модераторов прошу простить, я не знаю как и где искать именно это решение
всем заранее спсибо
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
И в чём конкретно проблема?
Как искать - можно вообще через гугл, а можно нажать красную ссылку сверху или снизу сообщений. Только диапазон дат лучше расширить - не за месяц искать а за всё время...
Как работать с веб-сервисом - поиск по словам "сервис", "POST", "XMLHTTP".
Как "разобрать" строку с json-ом - поиск по словам "JSON".
Как "записать в таблицу" - открыть хелп и читать про команду INSERT-SQL.

"Всё вместе" - ну написать в форум работа - может быть кто то за вас и напишет всю программу целиком


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Igor Korolyov Спасибо за ответ.
попробую объяснить в чем проблема.
есть веб сервис (wsdl) по локальному адресу
идет запрос из этого веб сервиса (результат полученных данных из веб сервиса я сохранил в aaa.xml)
и полученный результат необходимо сохранить в курсор.
вот кусочек кода:

o=CREATEOBJECT("MSSoap.SoapClient30")
o.MSSoapInit("http://172.106.100.25:8080/Service?wsdl")
loexception=NULL
tt=''
TRY
tt=o.GetAccountData(pin)
CATCH TO loexception
MESSAGEBOX(loexception.MESSAGE)
MESSAGEBOX(loexception.ERRORNO)
ENDTRY
IF ISNULL(loexception)
lcXML=tt.ITEM(0).parentnode.XML
LOCAL oXA AS XMLADAPTER
oXA = CREATEOBJECT("XMLAdapter")
oXA.LOADXML(lcXML,.F.,.T.)
oXA.TABLES[1].TOCURSOR(.F.,"testdata")
ENDIF
RELEASE o
CLOSE DATABASES

вот при создании курсора выходит сообщение Index or expression does not match an existing member of the collection.

да на этом форуме есть наверняка ответ. помогите правильно сформулировать поиск или ссылку дайте плз а еще лучше подсказать какой строки не хвататет в этом коде
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
rvc44

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
Не факт, что объект "MSSoap.SoapClient30" будет успешно создан в вашей системе. По крайней мере, в комплекте с VFP соответствующий класс не устанавливается по умолчанию. А Вы не пробовали обращаться к web-сервису по-другому:
LOCAL lcWSDL, ldDateOfFilling, lcReqDateTime, lcXMLFile, lcEnvPref, oXML, lcTarget, lI, lcPItext, oNewPI, lTry
LOCAL ARRAY laXML[5]
pcZapusk = 'C:\MyProgram\'
lcWSDL = 'http://172.106.100.25:8080/Service?wsdl'
* Дата направления запроса
ldDateOfFilling = DateTime()
* Дата и время первичного запроса для имени файла
lcReqDateTime = TTOC(ldDateOfFilling,1)
* Имя XML-файла с запросом
lcXMLFile = pcZapusk + "Out\Request1_" + lcReqDateTime + ".xml"
* Имя файла протокола
lcProtocol = pcZapusk + "Out\Протокол1_" + lcReqDateTime + ".txt"
* Создадим протокол
hFile = FCreate(lcProtocol)
If hFile = -1
= MessageBox('Не удалось создать файл протокола!',48,'Ошибка')
Return .F.
EndIf
* Запишем шапку протокола
lcStr = 'ПРОТОКОЛ ФОРМИРОВАНИЯ ЗАПРОСА К ВЕБ СЕРВИСУ'
FPuts(hFile, lcStr)
* Сформируем XML с запросом к web-сервису в переменной oXML
oXML = CREATEOBJECT("MSXML2.DOMDocument")
* Create a procesing instruction.
lcTarget = "xml" && oNewPI.Target
lcPItext = "version='1.0' encoding='UTF-8'"
oNewPI = oXML.CreateProcessingInstruction(lcTarget, lcPItext)
* Add the processing instruction node to the document.
oXML.AppendChild(oNewPI);
lcEnvPref = "soapenv"
* <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
oEnvelope = oXML.CreateElement(lcEnvPref + ":Envelope")
oEnvelope.SetAttribute("xmlns:" + lcEnvPref, "http://schemas.xmlsoap.org/soap/envelope/")
oXML.AppendChild(oEnvelope)
* <soapenv:Header>
oHeader = oXML.CreateElement(lcEnvPref + ":Header")
oEnvelope.AppendChild(oHeader)
* ... формирование XML-запроса
oXML.Save(lcXMLFile)
lcRequest = FileToStr(lcXMLFile)
* createRequestObject
laXML[1] = 'Msxml2.XMLHTTP.6.0'
laXML[2] = 'Msxml2.XMLHTTP.4.0'
laXML[3] = 'Msxml2.XMLHTTP.3.0'
laXML[4] = 'Msxml2.XMLHTTP'
laXML[5] = 'Microsoft.XMLHTTP'
For lI = 1 To 5
TRY
lTry = .T.
oXmlHttp = CREATEOBJECT(laXML[lI])
CATCH
lTry = .F.
ENDTRY
If lTry
EXIT
Else
LOOP
EndIf
EndFor
oXmlHttp.Open("POST", Left(m.lcWSDL, Len(m.lcWSDL)-5), .F.) && Обрежем "?wsdl"
oXmlHttp.setRequestHeader("Content-Type", "text/xml;charset=UTF-8")
* Вместо "" можно поставить нужное значение для SoapAction, либо оставить пустым:
oXmlHttp.setRequestHeader("SOAPAction", [""])
oXmlHttp.setRequestHeader("Content-Length", LTRIM(STR(LEN(lcRequest))))
lExitFunclion = .F.
TRY
*-- Запрос будем посылать в бинарном виде, поэтому добавляем к lcRequest слева явно 0h + ...
*-- Если сертификат, которым подписан XML-запрос просрочен, здесь получим ошибку:
*-- При обработке запроса произошла ошибка: Сертификат просрочен
oXmlHttp.Send(0h + lcRequest)
CATCH
lExitFunclion = .T.
ENDTRY
If !lExitFunclion
* Только при состоянии "complete"
Do While oXmlHttp.readyState <> 4
DoEvents Force
EndDo
lcResponseFile = pcZapusk + "Out\Response1_" + lcReqDateTime + ".xml"
If File(lcResponseFile)
=DeleteFile(lcResponseFile)
EndIf
lcResponseText = AllT(oXmlHttp.responseText)
StrToFile(lcResponseText, lcResponseFile)
lXML2HTML = .F.
lcErrMsg = "Запрос отправлен, но ответ содержит ошибку: "
If !Empty(hFile)
Do Case
Case oXmlHttp.Status = 200
If AT('<!DOCTYPE html',lcResponseText)>0 AND (AT('(ошибка 10060)',lcResponseText)>0 OR ;
AT('(ошибка 10061)',lcResponseText)>0)
lXML2HTML = .T.
FPuts(hFile, "Запрос отправлен не был, т.к. невозможно соединиться с удаленным сервером."+Chr(13)+;
"Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение.")
Else
FPuts(hFile, "Запрос отправлен и ответ успешно получен (статус 200)")
EndIf
Case oXmlHttp.Status = 400
FPuts(hFile, lcErrMsg + "(статус 400) Bad request")
Case oXmlHttp.Status = 401
FPuts(hFile, lcErrMsg + "(статус 401) Unauthorized")
Case oXmlHttp.Status = 402
FPuts(hFile, lcErrMsg + "(статус 402) PaymentRequired")
Case oXmlHttp.Status = 403
FPuts(hFile, lcErrMsg + "(статус 403) Forbidden")
Case oXmlHttp.Status = 404
FPuts(hFile, lcErrMsg + "(статус 404) Not found")
Case oXmlHttp.Status = 500
FPuts(hFile, lcErrMsg + "(статус 500) Internal server error")
Case oXmlHttp.Status = 501
FPuts(hFile, lcErrMsg + "(статус 501) Not implemented")
Case oXmlHttp.Status = 502
FPuts(hFile, lcErrMsg + "(статус 502) Service temporarily overloaded")
Case oXmlHttp.Status = 503
FPuts(hFile, lcErrMsg + "(статус 503) Gateway timeout")
EndCase
EndIf
= MessageBox(IIF(oXmlHttp.Status=200,IIF(lXML2HTML,'Запрос отправлен не был, т.к. невозможно соединиться с удаленным сервером.'+Chr(13)+;
'Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение.','Ответ на запрос получен.'),'Ответ содержит ошибку.')+;
IIF(lXML2HTML,'',' Статус: '+AllT(Str(oXmlHttp.Status)))+Chr(13)+Chr(13)+'Нажмите ОК для получения протокола.', 64, 'Статус полученного ответа')
If !Empty(hFile)
If lXML2HTML
FPuts(hFile, "Ошибка Proxy-сервера сохранена в файл " + lcResponseFile)
Else
FPuts(hFile, "Ответ, полученный на запрос сохранен в файл: " + lcResponseFile)
* Текст ответа на первичный запрос содержится в переменной lcResponseText
oXML = CREATEOBJECT("MSXML2.DOMDocument") && 'msxml2.DOMDocument.4.0'
* Не путать методы Load для файлов и LoadXML для строк, иначе будет ошибка:
* "Ошибка в элементе верхнего уровня документа."
* ("Invalid at the top level of the document.")
* Поскольку метод LoadXML не предназначен для загрузки файлов, а предназначен для загрузки
* строк, то сначала делаем lcResponseText = FileToStr(lcResponseFile),
* а затем обращаемся к LoadXML
lXMLLoaded = oXML.LoadXML(lcResponseText) && Возвращает .T. или .F.
If oXML.parseError.errorCode <> 0
oErrXML = oXML.parseError
* Не допускается, чтобы префикс пространства имен начинался
* с зарезервированной строки "xml". Проверяйте отсутствие таких конструкций:
* xmlns:xml="http://www.w3.org/XML/1998/namespace"
=MessageBox(oErrXML.reason + Chr(13) +;
'Вышлите разработчику файл:' + Chr(13)+ ;
lcResponseFile,16,'Ошибка загрузки XML-документа')
EndIf
If lXMLLoaded
* Определим, что вернулось в ответе: soapenv:Envelope
* Например: lcResponseText = '<SOAP-ENV:Envelope xmlns:SOAP-ENV=...'
lcEnvPrefPos = AT(':Envelope',lcResponseText)
&& ... Здесь осуществляется детальный разбор полученного XML-ответа
EndIf
EndIf
EndIf
EndIf
Release oXML
FClose(hFile)
WinToDos(lcProtocol, lcProtocol)
*-- Отобразим окно с файлом протокола, если он сформирован
If File(lcProtocol)
Do Form PfFile With lcProtocol, .T.
EndIf
* Процедура преобразования текстового файла из кодировки CP1251 (Win) в кодировку 866 (DOS)
PROCEDURE WinToDos
LPARAM pInFN, pOutFN
StrToFile(CPCONVERT(1251, 866, FileToStr(pInFN)), pOutFN)
RETURN
ENDPROC
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
rvc44
Не факт, что объект "MSSoap.SoapClient30" будет успешно создан в вашей системе. По крайней мере, в комплекте с VFP соответствующий класс не устанавливается по умолчанию. А Вы не
объект "MSSoap.SoapClient30" создан успешно. в комплекте VFP по умолчанию не было этого класса, но я до установил соответствующий патч и все заработало.
просто так как я в первые сталкиваюсь с веб сервисом, и теперь я кажется понял как надо правильно сформулировать вопрос к знатокам.
веб сервис возвращает данные в следующей структуре:
<GetAccountDataResult>
<a:AccountRecords>
<a:Activity/>
<a:AddSalary>0.00</a:AddSalary>
<a:Category>00
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
rvc44
Не факт, что объект "MSSoap.SoapClient30" будет успешно создан в вашей системе. По крайней мере, в комплекте с VFP соответствующий класс не устанавливается по умолчанию. А Вы не
объект "MSSoap.SoapClient30" создан успешно. в комплекте VFP по умолчанию не было этого класса, но я до установил соответствующий патч и все заработало.
просто так как я в первые сталкиваюсь с веб сервисом, и теперь я кажется понял как надо правильно сформулировать вопрос к знатокам.
веб сервис возвращает данные в следующей структуре:
<GetAccountDataResult>
<a:AccountRecords>
<a:Activity/>
<a:AddSalary>0.00</a:AddSalary>
<a:Category>001</a:Category>
<aateBegin>2007-02-14T00:00:00</aateBegin>
<aateEnd>2007-08-09T00:00:00</aateEnd>
<a:HighlandRate/>
<a:INN>00103199610159</a:INN>
</a:AccountRecords>
<a:ActuarialCoefficient>0.04</a:ActuarialCoefficient>
<a:CauseOfError>NO_ERRORS</a:CauseOfError>
<a:FirstName>Улукбек</a:FirstName>
<a:Flat/>
<a:House>38</a:House>
<a:LastName>Самыйбеков</a:LastName>
<a:Patronymic>Сатарбекович</a:Patronymic>
<a:Place>БИШКЕК</a:Place>
<a:Street>ыоларолр</a:Street>
<a:TotalStanding>08/07/10</a:TotalStanding>
<a:ZIPCode>720000</a:ZIPCode>

</GetAccountDataResult>

То есть исходя из этого я не правильно создаю курсор из этих данных, так как данные имеют не простую, а вложенную схему
Внимание вопрос
как из этого заполненого адаптера вытащить данные в курсор
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Он (сервис) возвращает объект с интерфейсом IXMLDOMNodeList? Если нет (что скорее всего так и есть), то зачем пытаться применить к нему .item(0)?
Откуда взята строка "<GetAccountDataResult> ....."? Это то что находится в переменной tt после завершения вызова, или это то что находится в переменной lcXML после соответствующей команды присвоения? На какую команду выдаётся указанная ошибка?

XMLAdapter сам по себе не сможет "разобрать" более/менее сложную структуру, тем более без схемы. Но ему можно "подсказать" как это делать - для постых случаев хватит и xsd схемы, для более сложных (в т.ч. и тех где нужно брать данные из разных узлов/уровней иерархии XML-домуента) - надо "вручную" настраивать XMLTables/XMLFields.

P.S. На сегодняшний день лучше не использовать MSSOAP компоненту, заменив её на "прямой" запрос через XMLHTTP. Как показано (хотя и весьма многословно) в примере Романа.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Igor Korolyov
Он (сервис) возвращает объект с интерфейсом IXMLDOMNodeList? Если нет (что скорее всего так и есть), то зачем пытаться применить к нему .item(0)?
Откуда взята строка "<GetAccountDataResult> ....."? Это то что находится в переменной tt после завершения вызова, или это то что находится в переменной lcXML после соответствующей команды присвоения? На какую команду выдаётся указанная ошибка?

XMLAdapter сам по себе не сможет "разобрать" более/менее сложную структуру, тем более без схемы. Но ему можно "подсказать" как это делать - для постых случаев хватит и xsd схемы, для более сложных (в т.ч. и тех где нужно брать данные из разных узлов/уровней иерархии XML-домуента) - надо "вручную" настраивать XMLTables/XMLFields.

P.S. На сегодняшний день лучше не использовать MSSOAP компоненту, заменив её на "прямой" запрос через XMLHTTP. Как показано (хотя и весьма многословно) в примере Романа.

Доброго времени суток!
Спасибо за отзыв!
GetAccountDataResult - это результат который возвращается при вызове метода GetAccountData(ПИН)
если честно я не разобрался что и как именно он(сервис) возвращает. мне кажется он возвращает обьект.
присваивая к переменной lcXML=tt.ITEM(0).parentnode.XML такое значение и сохраняя его в xml-файл я получил такой результат
<GetAccountDataResult>
<a:AccountRecords>
...
</a:AccountRecords>
<a:ActuarialCoefficient>0.04</a:ActuarialCoefficient>
<a:CauseOfError>NO_ERRORS</a:CauseOfError>
<a:FirstName>Улукбек</a:FirstName>
<a:Flat/>
<a:House>38</a:House>
<a:LastName>Самыйбеков</a:LastName>
<a:Patronymic>Сатарбекович</a:Patronymic>
<a:Place>БИШКЕК</a:Place>
<a:Street>ыоларолр</a:Street>
<a:TotalStanding>08/07/10</a:TotalStanding>
<a:ZIPCode>720000</a:ZIPCode>
</GetAccountDataResult>
мне сейчас нужен доступ к вложенным данным в
<a:AccountRecords>
<a:Activity/>
<a:AddSalary>0.00</a:AddSalary>
<a:Category>001</a:Category>
<aateBegin>2007-02-14T00:00:00</aateBegin>
<aateEnd>2007-08-09T00:00:00</aateEnd>
<a:HighlandRate/>
<a:INN>00103199610159</a:INN>
</a:AccountRecords>
Если честно у меня опыта писать на лисе маленький. время от времени в зависимости от задачи прибегаю к кодам. соответственно как работает xml-адаптер имею мало представления
подскажите как мне записать в курсор данные из <a:AccountRecords> ... </a:AccountRecords>
Спасибо заранее!
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну раз речь не про JSON а таки про XML, то в поиск по "XMLAdapter" - примеров хватает. Правда таким образом как делаешь ты, скорее всего не получится работать - я не вижу в твоём примере XML-я определений пространств имён, нечто типа xmlns:a="http://www.example.org/some" - без этого XML не является корректным... Но если на самом деле они там (в реальном XML-е) есть, то разобрать можно. Если не нужно в куроср вынимать данные из разных уровней иерархии, то даже не придётся париться с ручным прописыванием XMLName-ов для объектов XMLField - достаточно будет подготовить корректную xsd схему для твоей структуры.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Igor Korolyov
Ну раз речь не про JSON а таки про XML, то в поиск по "XMLAdapter" - примеров хватает. Правда таким образом как делаешь ты, скорее всего не получится работать - я не вижу в твоём примере XML-я определений пространств имён, нечто типа xmlns:a="http://www.example.org/some" - без этого XML не является корректным... Но если на самом деле они там (в реальном XML-е) есть, то разобрать можно. Если не нужно в куроср вынимать данные из разных уровней иерархии, то даже не придётся париться с ручным прописыванием XMLName-ов для объектов XMLField - достаточно будет подготовить корректную xsd схему для твоей структуры.

<GetAccountDataResult xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/PersonalAccountService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:AccountRecords>
<a:AccountRecord><a:Activity/><a:AddSalary>0.00</a:AddSalary><a:Category>001</a:Category><aateBegin>2016-12-01T00:00:00</aateBegin><aateEnd>2016-12-31T00:00:00</aateEnd></a:AccountRecord>
<a:AccountRecord><a:Activity/><a:AddSalary>0.00</a:AddSalary><a:Category>001</a:Category><aateBegin>2007-02-14T00:00:00</aateBegin><aateEnd>2007-08-09T00:00:00</aateEnd></a:AccountRecord>
...
</a:AccountRecords>
<a:ActuarialCoefficient>0.04</a:ActuarialCoefficient>
<a:CauseOfError>NO_ERRORS</a:CauseOfError>
<a:FirstName>Улукбек</a:FirstName>
<a:Flat/>
<a:House>38</a:House>
<a:LastName>Самыйбеков</a:LastName>
<a:Patronymic>Сатарбекович</a:Patronymic>
<a:Place>БИШКЕК</a:Place>
<a:Street>ыоларолр</a:Street>
<a:TotalStanding>08/07/10</a:TotalStanding>
<a:ZIPCode>720000</a:ZIPCode>
</GetAccountDataResult>

Спасибо за помощь! попробую создать схему и через него
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну это совсем другое дело - тут пространства имён на месте По идее адаптер (после подсовывания ему корректной схемы) без проблем достанет то что внутри AccountRecords. Вот с тем что внутри корневого узла GetAccountDataResult будут вопросы... Но в принципе всё решаемо - если и не "чисто схемой", то прописыванием нужных xpath путей для XMLName соответствующих объектов. В крайнем случае можно и вручную брать данные через метод SelectSingleNode - благо XML возвращается уже сразу в виде DOM-а, т.е. объекта из состава MSXML парсера...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
[attachment 26857 xml_xsd.rar]у меня совсем не получается все время выходит ошибка Index or expression does not match an existing member of the collection

веб сервис возвращает данные в объект tt и я присваиваю к переменной lcXML данные из объекта tt и сохраняю в файл bbb.xml (для проверки что веб сервис выплевывает)

pin = '20212198701159'
SET TALK OFF
o=CREATEOBJECT("MSSoap.SoapClient30")
o.MSSoapInit("http://172.16.100.25:8080/RestManagerFundsService?wsdl")
loexception=NULL
tt=''
TRY
tt=o.GetAccountData(pin)
CATCH TO loexception
MESSAGEBOX(loexception.MESSAGE)
MESSAGEBOX(loexception.ERRORNO)
ENDTRY
CREATE CURSOR AccountRecord(;
Activity char(3),;
AddSalary double(2),;
DateBegin DATE, DateEnd date,;
HighlandRate char(3),;
INN char(14),;
Income double(2),;
IndexationCoefficient double(2),;
MedicineFundSum double(2),;
Month integer,;
NumSF char(14), OKPO char(8), ;
PFUnitedPart double(2), ;
Payer char(50), ;
PensionFundPaymentSum double (2), ;
PensionFundSum double (2), ;
PerEmpr double (2), ;
Percent double (2), ;
PreEmpe double (2), ;
Privilege char(10), ;
RUSF char(3), ;
SFUnitedPart double (2),;
SP2 double (2), ;
Salary double (2), ;
SalaryFull double (2), ;
SavingFundPaymentSum double (2), ;
SavingFundSum double (2), ;
Standing char(10), ;
SumEmpe double (2), ;
SumEmpr double (2), ;
Voluntary char(1),;
Year integer)
IF ISNULL(loexception)
lcXML=tt.ITEM(1).parentnode.XML
STRTOFILE(lcXML,'bbb.xml')
LOCAL oXA as XMLAdapter, oXT as XMLTable, oXF as XMLField
oXA = CREATEOBJECT("XMLAdapter")
oXA.LoadXML(lcXML,.F.,.T.)
oXA.XMLSchemaLocation="lss.xsd"
IF USED('AccountRecord')
USE IN AccountRecord
ENDIF
oXA.TABLES[2].TOCURSOR(.F.,"AccountRecord")
ENDIF
RELEASE o

Я приатачил файл bbb.xml и lss.xsd

Уважаемые господа. Помогите где у меня чего не хватает.
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Схема некорректная (регистр, пространства имён). Кроме того, в таком виде она слишком сложная, не уверен что адаптер сможет разобрать... Ну разве что выкинуть описание полей вне узла AccountRecords (т.е. использовать "неполную" схему) и подшаманить с префиксом у корневого элемента (он получается не из того пространства имён что все прочие элементы)... Впрочем, это сложный и муторный путь

Если же вынуть только узел AccountRecords, то всё станет значительно проще... Там даже тривиальным XMLTOCURSOR() вообще без схемы можно получить курсор с данными. Ну, конечно, и через адаптер с корректной схемой (в данном случае она будет простой) можно...

Из MXSML2.DomDocument объекта выбор только XML текста для узла узла AccountRecords делается кодом типа
loDOM.setProperty("SelectionNamespaces",[xmlns:ns1="http://schemas.datacontract.org/2004/07/PersonalAccountService"])
lcXML = loDOM.SelectSingleNode("//ns1:AccountRecords").xml
У тебя, по идее, выйти на DomDocument из этого tt можно через tt.item(0).ownerDocument - вероятно сервис возвращает объект "коллекция узлов"... Только лучше перестраховаться и делать всё по шагам - т.е. сначала проверить что tt.length > 0... Ну или ошибки на соответствующих строках перехватывать каким try catch - т.к. в случае "пустого ответа" будет нехорошо работать.
P.S. сам курсор ни так ни этак делать не обязательно - это если бы мы работали не через схему, тогда да - но это совсем другой вариант, и он слишком "многословный" - там нужно пустой курсор погрузить в адаптер через AddTableSchema, а потом вручную перебивать все XMLName для получившихся XMLTable (что ещё пол беды) и XMLField (а тут то как раз писанины...) Примеры как работать по такой схеме есть на форуме. Из плюсов - можно вынуть в этот же курсор данные из узлов вне списка - т.е. FirstName, LastName - но я бы не стал так делать, всё ж это мастер-детали схема, и сливать все поля в одну таблицу не очень хорошо...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Igor Korolyov
Схема некорректная (регистр, пространства имён). Кроме того, в таком виде она слишком сложная, не уверен что адаптер сможет разобрать... Ну разве что выкинуть описание полей вне узла AccountRecords (т.е. использовать "неполную" схему) и подшаманить с префиксом у корневого элемента (он получается не из того пространства имён что все прочие элементы)... Впрочем, это сложный и муторный путь
Если же вынуть только узел AccountRecords, то всё станет значительно проще... Там даже тривиальным XMLTOCURSOR() вообще без схемы можно получить курсор с данными. Ну, конечно, и через адаптер с корректной схемой (в данном случае она будет простой) можно...

Из MXSML2.DomDocument объекта выбор только XML текста для узла узла AccountRecords делается кодом типа
loDOM.setProperty("SelectionNamespaces",[xmlns:ns1="http://schemas.datacontract.org/2004/07/PersonalAccountService"])
lcXML = loDOM.SelectSingleNode("//ns1:AccountRecords").xml
У тебя, по идее, выйти на DomDocument из этого tt можно через tt.item(0).ownerDocument - вероятно сервис возвращает объект "коллекция узлов"... Только лучше перестраховаться и делать всё по шагам - т.е. сначала проверить что tt.length > 0... Ну или ошибки на соответствующих строках перехватывать каким try catch - т.к. в случае "пустого ответа" будет нехорошо работать.
P.S. сам курсор ни так ни этак делать не обязательно - это если бы мы работали не через схему, тогда да - но это совсем другой вариант, и он слишком "многословный" - там нужно пустой курсор погрузить в адаптер через AddTableSchema, а потом вручную перебивать все XMLName для получившихся XMLTable (что ещё пол беды) и XMLField (а тут то как раз писанины...) Примеры как работать по такой схеме есть на форуме. Из плюсов - можно вынуть в этот же курсор данные из узлов вне списка - т.е. FirstName, LastName - но я бы не стал так делать, всё ж это мастер-детали схема, и сливать все поля в одну таблицу не очень хорошо...
переменная loDOM каким образом должна объявляться каким типом? СПС за ранее
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Фокс нетипизированный язык, не нужно ему ничего указывать про типы.
Эта переменная у меня приведена чисто для иллюстрации идеи - какой метод объекта нужно использовать. Как получить ссылку на такой объект (хотя тут я не могу ничего гарантировать - это лишь предположение, на основании того как в твоём коде был получен текст xml-документа) написано чуть ниже.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
U_LooK
Автор

Сообщений: 19
Откуда: Bishkek
Дата регистрации: 04.12.2009
Igor Korolyov
Фокс нетипизированный язык, не нужно ему ничего указывать про типы.
Эта переменная у меня приведена чисто для иллюстрации идеи - какой метод объекта нужно использовать. Как получить ссылку на такой объект (хотя тут я не могу ничего гарантировать - это лишь предположение, на основании того как в твоём коде был получен текст xml-документа) написано чуть ниже.
Я уже совсем запутался.
Поставлю вопрос иначе
у меня есть некий веб сервис из которого я получаю данные следующим образом

pin = '20212198701159'
o=CREATEOBJECT("MSSoap.SoapClient30")
o.MSSoapInit("http://172.16.100.25:8080/RestManagerFundsService?wsdl")
lcXML=tt.ITEM(0).parentnode.XML

На всякий случай полученный XML файл сохраняю на диск следующим образом
STRTOFILE(lcXML,'aaa.xml')
внутри сохраненного файла появились следующие строки
<GetAccountDataResult xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/PersonalAccountService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:AccountRecords>
<a:AccountRecord>
<a:Activity>999</a:Activity>
<a:AddSalary>0.00</a:AddSalary>
<a:Category>001</a:Category>
<aateBegin>2006-09-01T00:00:00</aateBegin>
<aateEnd>2006-09-30T00:00:00</aateEnd>
<a:HighlandRate/>
</a:AccountRecord>
<a:AccountRecord>
<a:Activity/>
<a:AddSalary>0.00</a:AddSalary>
<a:Category>001</a:Category>
<aateBegin>2010-08-01T00:00:00</aateBegin>
<aateEnd>2010-08-31T00:00:00</aateEnd>
<a:HighlandRate/>
</a:AccountRecord>
</a:AccountRecords>
<a:ActuarialCoefficient>0.04</a:ActuarialCoefficient>
<a:CauseOfError>NO_ERRORS</a:CauseOfError>
<a:FirstName>Кенжебек</a:FirstName>
<a:Flat/>
<a:House>12</a:House>
<a:LastName>Киязов</a:LastName>
<a:Patronymic>Кадырбекович</a:Patronymic>
<a:Place/>
<a:Street>Онбир-Жылга у Калмурса</a:Street>
<a:TotalStanding>06/10/02</a:TotalStanding>
<a:ZIPCode>722203</a:ZIPCode>
</GetAccountDataResult>

Теперь мне надо из этого веб сервиса получить таблицу или курсор с данными по столбцам из узла <a:AccountRecord>
то есть курсор должен иметь следующие столбцы с данными
AddSalary, Category, DateBegin, DateEnd, HighlandRate
Может для кого то тривиальная задача, но для меня сложновато.
Люди добрые подскажите или напишите какие там должны быть строки кода чтобы решить мою маленькую задачу.
Может быть поможет... я долго копался в самом веб сервисе и я там откапал xsd схему
вот так она выглядит

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.datacontract.org/2004/07/PersonalAccountService" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/PersonalAccountService">
<xs:complexType name="PersonalAccountData">
<xs:sequence>
<xs:element minOccurs="0" name="AccountRecords" nillable="true" type="tns:ArrayOfAccountRecord"/>
<xs:element minOccurs="0" name="ActuarialCoefficient" type="xs:decimal"/>
<xs:element minOccurs="0" name="CauseOfError" type="tns:ServiceErrors"/>
<xs:element minOccurs="0" name="FirstName" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Flat" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="House" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="LastName" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Patronymic" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Place" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Street" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="TotalStanding" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="ZIPCode" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="PersonalAccountData" nillable="true" type="tns:PersonalAccountData"/>
<xs:complexType name="ArrayOfAccountRecord">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="AccountRecord" nillable="true" type="tns:AccountRecord"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfAccountRecord" nillable="true" type="tns:ArrayOfAccountRecord"/>
<xs:complexType name="AccountRecord">
<xs:sequence>
<xs:element minOccurs="0" name="Activity" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="AddSalary" type="xs:decimal"/>
<xs:element minOccurs="0" name="Category" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="DateBegin" type="xs:dateTime"/>
<xs:element minOccurs="0" name="DateEnd" type="xs:dateTime"/>
<xs:element minOccurs="0" name="HighlandRate" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="AccountRecord" nillable="true" type="tns:AccountRecord"/>
<xs:simpleType name="ServiceErrors">
<xs:restriction base="xs:string">
<xs:enumeration value="NO_ERRORS"/>
<xs:enumeration value="PIN_INCORRECT"/>
<xs:enumeration value="PIN_NOTFOUND"/>
<xs:enumeration value="PIN_INACTIVE"/>
<xs:enumeration value="MK_WRONG"/>
<xs:enumeration value="INTERNAL_ERROR"/>
<xs:enumeration value="ACTUARIAL_COEF_NOTFOUND"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="ServiceErrors" nillable="true" type="tns:ServiceErrors"/>
</xs:schema>

Я тут везде указываю только 5 полей схемы на самом деле там более 20 полей. И так мой пост так многословен.
Спасибо всем заранее.
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ещё раз по буквам:
lcXML=tt.ITEM(0).parentnode.XML
loDOM = tt.item(0).ownerDocument
loDOM.setProperty("SelectionNamespaces",[xmlns:ns1="http://schemas.datacontract.org/2004/07/PersonalAccountService"])
lcXML = loDOM.SelectSingleNode("//ns1:AccountRecords").xml
? XMLTOCURSOR(m.lcXML)
BROWSE


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
of63

Сообщений: 25161
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() Вобще, ... я нифика не понял, в каждой строке - ничего, хоть комментариями бы снабдил...
Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
Simple777

Сообщений: 33855
Дата регистрации: 05.11.2006
"В каждой строчке только точки после буквы л... Сказать Понять хотел, но не сумел..." :al:

Ratings: 0 negative/0 positive
Re: как заполнить таблицу из веб сервиса
of63

Сообщений: 25161
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() Что начиналась с буквы "Л", заканчиваясь мягким знаком
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 16 (Гостей: 16)

© 2000-2024 Fox Club 
Яндекс.Метрика