Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.

Problem accessing XML values from webservice call to SAP. Javascript, LiveCycle ES8.2

Avatar

Level 1

Guys

I am finding difficulty accessing the values of XML data supplied from a webservice call (to a SAP ABAP webservice).  I am using LiveCycle 8.2 and javascript.  The web service itself uses Document style binding in the WSDL.  My javascript specifies XML binding (though I have also tried Message and JS style binding.)

When I execute the webservice call, I can use SOAP.wireDump = true; to see the contents of the XML returned (see a brief excerpt below):

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header></soap-env:Header>
<soap-env:Body><n0:ZFMWSResponse xmlns:n0="urn:sap-com:document:sap:soap:functions:mc-style">

<Contents>
     <Item>
     <Name>String</Name>
     </Item>
</Contents>

<ReturnContents>

     <Item>
     <Name>String1</Name>
     <Item>

     <Item>
     <Name>String2</Name>
     </Item>
</ReturnContent>

etc etc

This XML is stored within a variable called "result".

Now it gets interesting.  I can easily access the value of the <Contents><Item><Name> </Name> string (i.e. String1) using the following javascript syntax:

console.println(result.Contents.Item.Name);

This syntax (i.e. result.Contents.Item.Name) also works when I display the result in a form text field.

This is slightly curious as I would have anticipated that .value or .soapValue would be required to access the value, but no, simply using the syntax above retrieves the value.

Why this works I am unsure.  However.  When there is more than one repeating value in the XML i.e. there are two <Item> instances in <ReturnContents>, I cannot find a valid syntax to access any of their values.

For example,

console.println(result.ReturnContents.Item[0].Name); does not work!

I do not seem to be able to find any syntax that accesses the value of <Item> when there are multiple instances of Item in the XML.

I have tried many things including trying to parse the contents or result into XML i.e.:

var myXML = XMLData.parse(result, false);
var a = XMLData.applyXPath(result, "//item");
a.saveXML('pretty');

If this worked, I could then easily navigate through to the values I need.

etc etc.

However this always causes an error.  When this script runs the contents of 'result' (which is storing the XML returned from the webservice) always appear to be empty.  The error is: Xml parsing error: no element found (error code 3).

Does anyone have any ideas?  The main problem seems to be that I cannot properly access the properties of the 'result' variable which holds the XML returned from the web service.

The only property of this 'result' vairable which returns something other than null or empty is:

result.ReturnContents.length;

This then returns the number of <Items> under the <ReturnContents> node.  However, result.ReturnContents.value (or any similar syntax) always returns empty.

What is the syntax to access multiple <Items> under <ReturnContents>?


Any thoughts would be very much appreciated!
Thanks
Roxy

6 Replies

Avatar

Former Community Member

You are using two different technologies to look at the result of your web service.

The SOAP.wiredump is the Acroform way of looking at soap results. It creates a results object for and hence you can navigate down the tree (without a value param) to get what you are after.

When you start trying to manipulate the XML you are using XFA commands. Generally the two do not mix.

As a solution to your issue I woudl load the wsdl for your service in the Data Connection view and if you are getting a single XML stream back then assign the output to a multiline field. Then you coudl load the xml into the data dom and now those commands that you have been using will work.

There have been a couple of posts about loading returned XML into the Dom so you might want to search on those as well.

Hope that helps

Paul

Avatar

Level 1

Thank you for your response.

I think I understand but would like to validate your recommendation.  I am also encountering a parsing error which I will describe.

Firstly, a bit more info.  My web service call is fairly simple and detailed below.

var service = SOAP.connect({
cURL: cURL,
cResponseStyle: SOAPMessageStyle.XML,        
oAuthenticate: oAuthenticator
});


result = service.ZDataService();

When ran, this then returns a SOAP Envelope containing XML to the result variable.

An example of this envelope is provided below.

i.e.
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header></soap-env:Header>
<soap-env:Body><n0:ZFMWSResponse xmlns:n0="urn:sap-com:document:sap:soap:functions:mc-style">

<Contents>
<Item>
<Name>String</Name>
</Item>
</Contents>

<ReturnContents>

<Item>
<Name>String1</Name>
<Item>

<Item>
<Name>String1</Name>
</Item>
</ReturnContent>

etc etc

As I understand from your and other posts, I have two options on retrieving the contents of the XML.


One
I can either parse the results and then navigate the parsed xml i.e.

var myXML = XMLData.parse(result, false);
var a = XMLData.applyXPath(result, "//item");
a.saveXML('pretty');

Following which I should easily be able to access the XML contents...

Two
I can parse the XML, add it to the DOM, and then use xfa.resolveNode etc to access its data..

Do you agree with these two options?

However, my main problem currently is that I get two different errors when I try to parse the soap envelope returned by the web service.

(a) If I use XMLData.parse(result, false) where the 'result' variable holds the response from the web service, I get:


GeneralError: Operation failed.

XMLData.parse:53:XFA:form1[0]:#subform[0]:Button1[0]:click
GeneralError: Operation failed.
XFAObject.loadXML:-1:XFA:form1[0]:#subform[0]:Button1[0]:click
Xml parsing error: no element found (error code 3), line 1, column 1 of file

(b) If I pass the result of the webservice into a plain text multiline text field on the Form, and try to parse the contents, I get the following error:

GeneralError: Operation failed.
XMLData.parse:53:XFA:form1[0]:#subform[0]:Button1[0]:click
GeneralError: Operation failed.
XFAObject.loadXML:-1:XFA:form1[0]:#subform[0]:Button1[0]:click
Xml parsing error: syntax error (error code 2), line 1, column 1 of file

Any thoughts?  Is it possible the XML parser in LiveCycle 8.0 is unable to process the SOAP envelope produced by the SAP stack?

As noted the SOAP envelope returned from the web service has the following syntax:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header></soap-env:Header>
<soap-env:Body><n0:ZFMWSResponse xmlns:n0="urn:sap-com:document:sap:soap:functions:mc-style">

Many thanks for your help.

Roxy

Avatar

Former Community Member

You are still mixing methods.

There is nothing wrong with using the AcroForm method...but I prefer the XFA way (if it suits yoru web service).

In Designer under the Data Connection you can choose a wsdl to connect to. This will imspect the wsdl and will expose any INputs and outputs in a tree structure in that view. You can then drag and drop the inputs and outputs of the web service onto the appropriate fields on your form this setting up bindings between the two. There is also a button definition provided in the data view. You can drag that onto the form and when you press it the web service executes and the bindings are run and your fields are populated.

Make sense?

Paul

Avatar

Level 1

Hi Paul

Sorry but the web service call has to be made programmatically.  The target version of Acrobat/Livecycle does not support authentication via the Data Connection method.  I therefore need to make the call using JavaScript.  If anyone can therefore respond to the queries in my thread above, this would be very helpful.

Thanks

Roxy

Avatar

Former Community Member

Just as a point of interest that technique does support a secure web service call.A dialog will appear allowing you to enter the credentials when you execute the service; however you will not be able to put the credentials in the call programmatically (I then question why there is security on the WS at all if you are going to hardcode a program to enter the credentials).

Paul

Avatar

Former Community Member

Hello RoxyOzGirl,

I have the same problem ... were you able to access the returned data?

I would like to do the acces programmatically but I found some difficulties and my meantime solution is to use the postExecute event of the button in order to manage the returned data from the WS. Obviously with this solution I need to define the Data Connection for the WS, which I would like to avoid and in the case that authentication is needed it won't work.

in the XML Source add the event to the button

<

event activity="postExecute" ref="xfa.connectionSet.<ConnectionName>" name="event__postExecute">

the event postExecute will appear in the JavaScript editor for "Events with Scripts" where you have to write your code to acces to the returned WS data

items

= xfa.datasets.connectionData.<ConnectionName>.Body.<WS_RESPONSE>.<TABLE>.<TABLE_LINE>.all;

for (i = 0; i < items.length; i++) {

     instance

= <RESULT_FORM>.<RESULT_TAB>._<RESULT_TAB_LINE>.addInstance(1);

     instance.<FIELD>.rawValue = items.<TABLE_LINE>(i).<FIELD>.value;

}

In any case, I am not happy with this solution, as I would like do it 100% programmatically.

Kind regards,

G.