I am writing a SOAP webservice client (which is provided by others). I have imported WSDL and called request, servise respondes an XML like below. I can reach (DeliveryNumberList array's item DeliveryNumber) DeliveryNumber's PackingSlipNo and VendorAccount attributes but i need to reach DeliveryNumber's value (008740774). In the class file (which Delphi generated from WSDL) there is no option to reach this value. Someone have any idea?
<ns1:Results>
<ns1:Result>
<ns1:Status>true</ns1:Status>
<ns1:Message>Başarılı</ns1:Message>
<ns1:VendorAccount/>
<ns1:DeliveryNumberList>
<ns1:DeliveryNumber PackingSlipNo="X100327233" VendorAccount="0002230728">008740774</ns1:DeliveryNumber>
</ns1:DeliveryNumberList>
</ns1:Result>
</ns1:Results>
If you are able to extract the value of VendorAccount, it should be possible to extract also the value of DeliveryNumber.
May be you could show some code how you extract the value of VendorAccount.
PS: can not add comment because not enough reputation, therefore posting as answer
Here is some code that extracts the value from a XML:
myXML.LoadFromFile(FileOpen.FileName);
memo1.Lines.Add('LocalName:'+myXML.DocumentElement.LocalName);
nrChildNodes := myXML.DocumentElement.ChildNodes.Count;
memo1.Lines.Add('ChildNodes:'+inttostr(nrChildNodes) );
aNode := myXML.DocumentElement.ChildNodes[0].ChildNodes.FindNode('DeliveryNumberList');
if aNode <> nil then
begin
memo1.Lines.Add('aNode.LocalName:'+aNode.LocalName);
memo1.Lines.Add('DeliveryNumber='+aNode.ChildValues['DeliveryNumber']);
end
else memo1.Lines.Add('aNode = nil');
Related
I write this code for button click event . the first time I click the button every thing work correctly but when click for the second time on button it raise an error. whats the problem?
procedure TfrmMain.Button1Click(Sender: TObject);
var
B : Boolean;
begin
DM.tblTemp.DisableControls;
B:= DM.tblTemp.Locate('FoodName', DM.tblAsli.FieldByName('FoodName').AsString,[]) ;
if B then
begin
DM.tblTemp.Edit;
DM.tblTemp.FieldByName('Number').AsInteger:= DM.tblTemp.FieldByName('Number').AsInteger + 1;
DM.tblTemp.Post;
end
else
begin
DM.tblTemp.insert;
DM.tblTemp.FieldByName('FoodName').AsString := DM.tblAsli.FieldByName('FoodName').AsString;
DM.tblTemp.FieldByName('UnitPrice').AsInteger := DM.tblAsli.FieldByName('FoodPrice').AsInteger;
DM.tblTemp.FieldByName('Number').AsInteger := 1;
DM.tblTemp.Post;
end;
TotalPrice:= TotalPrice + DM.tblTemp.FieldByName('TotalPrice').AsInteger;
DM.tblTemp.EnableControls;
end;
the Error is
Row cannot be located for updating. Some values may have been changed
since it was last read
DM is data madual
tmbTbl is ADOTable
It is a pity you haven't said which DBMS you are using (e.g. Sql Server or MS Access,
nor told us a full list of the table's column types and indexes, if any.
The most likely answer to your q is that the variable B is set to False the first time
because the call to tblTemp.Locate fails to locate the Food name in question, so the Insert branch executes and the food's data is
added to the table but the second time the Edit branch executes and the error occurs,
though you have not said where, exactly. My guess would be on the call to .Post, because
the error message is one the ADO layer, which sits between the DBMS provider and your app,
emits when it attempts to post a change to the table but cannot identify which table row to update.
As I mentioned in a comment, the fix to this is usually at add a primary key index to the table, and I gather from your latest comment that this has succeeded for you. For the record and benefit of future readers it would be helpful if you could confirm which DBMS you are using and which Ole Driver you are using in your connection string.
Fwiw, I've tested your code using a table on MS Sql Server and MS Access and do not get the
error with either database.
Btw there is an obvious q, "How is it that tblTemp.Locate succeeds, but ADO is unable to
identify the correct record to post the update?" The answer is that tblTemp.Locate works in
a different way than identifying the relevant row to post the update.
Trying to insert simple xml file with one row in IIB with simple message flow into Oracle XE DB. Message flow works fine and inserts data into database, but data written in db is different from starting data. For example, as I'm trying to insert my name "Dino" I'd get Korean/Japanese/Chinese signs in return.
I've tried changing XML formats thinking there might be problem, but I suppose it has to do with encoding.
Input:
Output in DB:
This is how my compute node looks like:
CREATE COMPUTE MODULE SimpleDB_mf_Compute
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
CALL CopyMessageHeaders();
-- CALL CopyEntireMessage();
INSERT INTO Database.dkralj.emp VALUES(InputRoot.XMLNSC.emp.name);
SET OutputRoot.XMLNSC.DBINSERT.STATUS='SUCCESS';
RETURN TRUE;
END;
CREATE PROCEDURE CopyMessageHeaders() BEGIN
DECLARE I INTEGER 1;
DECLARE J INTEGER;
SET J = CARDINALITY(InputRoot.*[]);
WHILE I < J DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I = I + 1;
END WHILE;
END;
CREATE PROCEDURE CopyEntireMessage() BEGIN
SET OutputRoot = InputRoot;
END;
END MODULE;
Looking at the IBM documentation for the INSERT statement in ESQL it might be worth trying.
INSERT INTO Database.dkralj(NAME) VALUES(InputRoot.XMLNSC.emp.name);
If weird things are still happening then I'd try a string constant to avoid any issues with character coding in the input message.
INSERT INTO Database.dkralj(NAME) VALUES('TheEmpValue');
Before this statement in your code
SET OutputRoot.XMLNSC.DBINSERT.STATUS='SUCCESS';
You should check for success or otherwise by using the inbuilt SQLSTATE, SQLCODE, SQLERRORTEXT to check the result of your call.
IF NOT ((SQLCODE = 0) OR (SQLSTATE = '01000' AND SQLNATIVEERROR = 8153)) THEN
-- Do something about the error.
-- The check of SQLSTATE and SQLNATIVEERROR covers warnings
-- The 8153 is for Microsoft SQL Server other databases may use a different value
END IF;
Also check the codepages aka CodedCharSetId of the source system data, the message in IIB and the default codepage of the database.
Use mqsicvp MYBROKER -n ODBC_DB_NAME to get other details about the connection you need to use -n to get the details.
Use something like DBeaver to add some data. Have a look at the datatype specified for the field.
As per your comment below and my response here is an example of a PASSTHRU statement. Note the use of the ? to avoid SQL Injection.
PASSTHRU('SELECT RTRIM(A.EMPLID) AS EMPLID,
RTRIM(A.ADDRESS_TYPE) AS ADDRESS_TYPE,
RTRIM(A.ADDR_TYPE_DESCR) AS ADDR_TYPE_DESCR,
CAST(RTRIM(A.EFFDT) AS DATE) AS EFFDT,
RTRIM(A.EFF_STATUS) AS EFF_STATUS,
RTRIM(A.ADDRESS1) AS ADDRESS1,
RTRIM(A.ADDRESS2) AS ADDRESS2,
RTRIM(A.ADDRESS3) AS ADDRESS3,
RTRIM(A.ADDRESS4) AS ADDRESS4,
RTRIM(A.CITY) AS CITY,
RTRIM(A.STATE) AS STATE,
RTRIM(A.POSTAL) AS POSTAL
FROM ADDRESS_VW AS A
WHERE UPPER(A.EMPLID) = ?') VALUES(AggrRef.EmployeeID)
I would to save an email attachment to a file using a TIdImap4 object of Indy Ver.10.
I get the UID of the email, then I use this code:
lMsg := TIdMessage.Create(Self);
lImap.UIDRetrieveStructure(lUid, lMsg);
lMsg.MessageParts.CountParts;
if lMsg.MessageParts.AttachmentCount > 0 then
for lJ := 0 to lMsg.MessageParts.Count - 1 do
if (lMsg.MessageParts[lJ] is TIdAttachment) and
SameText(lMsg.MessageParts[lJ].Name, 'MyAttachment') then
lImap.UidRetrievePartToFile(lUid, lJ, lDimAllegato, lFileName, Trim(lMsg.MessageParts[lJ].ContentTransfer))
This worked until lMsg.MessageParts[lJ].ContentType = 'Text/Plain' and
lMsg.MessageParts[lJ].ContentTransfer = '7bit', now UidRetrievePartToFile() returns False and no file is created. I suppose because
lMsg.MessageParts[lJ].ContentType = 'application/octet-stream' and
lMsg.MessageParts[lJ].ContentTransfer = 'base64'.
I'm not skilled on this topic, what I need to change in code in order to save this type of attachment?
I also tried with: TIdAttachment(lMsg.MessageParts[lJ]).SaveToFile(lFileName)
and similar, but the file created was always empty.
Using UIDRetrieveStructure() with a TIdMessage is going to fill the TIdMessage.MessageParts with a lot of TIdttachment objects, never any TIdText objects, and not all of the objects are going to represent actual attachments. You are using the TIdAttachment indexes as the APartNum parameter of UIDRetrievePartToFile(), which might not be accurate.
And you can't use TIdAttachment.SaveToFile() when using UIDRetreiveStructure(), because no actual data has been downloaded, only the structure of the email, which then allows you to download the data for the specific elements you want.
I suggest you use the other overloaded version of UIDRetrieveStructure() that fills a TIdImapMessageParts instead. Amongst other things, TIdImapMessagePart gives you an exact ImapPartNumber that you can then give to UIDRetrievePartToFile() (as well as the ContentTransferEncoding):
lParts := TIdImapMessageParts.Create(nil);
try
lImap.UIDRetrieveStructure(lUid, lParts);
for lJ := 0 to lParts.Count - 1 do
begin
if (lParts[lJ] is the desired attachment) then
begin
lImap.UidRetrievePartToFile(lUid, lParts[lJ].ImapPartNumber, lDimAllegato, lFileName, lParts[lJ].ContentTransferEncoding);
end;
end;
finally
lParts.Free;
end;
Hi guys i've written a function which has to check the ID given to the function as iID and then output the name of the member of it is found, otherwise it must output that it is not found
A different table is active when this function is called so it must change the table to Members (to search the ID) and then back again afterwards (I have multiple tables)
function fCheckID(iID:integer):String;
var sTable:string;
begin
sTable:=datamoduleX.tableX.TableName;
datamoduleX.tableX.TableName:='Members';
if datamoduleX.tableX.Locate('RefNo',iID,[]) then
result:=dmRooiX.tblRooiX['Name']+' '+datamoduleX.tableX['Surname']
else
result:='ID: '+inttostr(iID)+' does not exist';
datamoduleX.tableX.TableName:=sTable;
end;
but the problem is every time I call this function I get an error that says "Cannot perform this operation on an open dataset"
if I close the dataset before I run the function I get "Cannot perform this operation on a closed dataset"
I know the error occurs when I try to access the table name or change it (the function does not give the error when those 3 lines are commented out)
I have no idea how to make this work
any help would be greatly appreciated
Example :
Table1.TableName := 'TABLE1';
Table1.Open;
Table1.TableName := 'TABLE2'; <-- Cannot perform this operation on Open data set. Because Table1 is open
Table1.Locate('ID',11,[]);
simple solution
Table1.TableName := 'TABLE1';
Table1.Open;
Table1.Close; <--Close table before change table name
Table1.TableName := 'TABLE2';
Table1.Open; <-- Open new table before do Locate
Table1.Locate('ID',11,[]);
I had a multi tier project in which i would collect data from a microsoft sql 2005 through a FDStoredProc with a function and the function would return a dataset to the client. When the server assigns the dataset to the result of the function and the function tries to send it to the client i get this error. Project etctec.exe raised exception class TDBXError with message 'TDBXTypes.BLOB value type cannot be accessed as TDBXTypes.Bytes value type'.
In another project i used the StoredProc of a different database with TFDStoredProc in exactly the same way and it works fine. Any ideas what would raise this error?
This is what i do in the server.
function TServerMethods1.getCategories(): TDataSet;
begin
FDStoredProc1.ParamByName('#val1').AsInteger:= 1;
FDStoredProc1.ParamByName('#val2').AsInteger:= 0;
FDStoredProc1.ParamByName('#val3').AsInteger:= 1;
FDStoredProc1.ParamByName('#val4').AsInteger:= 1;
FDStoredProc1.Open();
result:= FDStoredProc1;
end;
and the client calls it like this...
dataset:=ClientModule1.ServerMethods1Client.getCategories();
Problem comes from some fields that are of type NVARCHAR(max), anyone knows a workaround to this error without changing the field type?
I tried changing the dataset's field type to a string or something with no success. The only thing i can temporarily do is get these fields separately, put them in a stringlist or something like that and pass it to the client.
I think you should use some of similar methods below:
http://docwiki.embarcadero.com/Libraries/XE4/en/Data.DB.TDataSet.CreateBlobStream
http://docwiki.embarcadero.com/Libraries/XE4/en/Data.DB.TDataSet.GetBlobFieldData
You should define you field as a blob field and then put data in/out with the functions described in the links.
Here is also example how to copy data:
http://docwiki.embarcadero.com/Libraries/XE4/en/Data.DB.TDataSet.CreateBlobStream