Namespace nightmare?

D

DGibson

I am currently testing using the GetMyProfile web service that is included
with Microsoft's Status Report example. The web service is installed and the
Status Report sample form works just fine.

I created a new form and setup a data connection to the webservice and can
query the service without any problem. What I'm trying to do now is to use
JScript to grab the data and put it in a variable that I can then use.

function XDocument::OnLoad(eventObj)
{
var oWebService = XDocument.DataObjects.Item("GetMyProfile");
oWebService.DOM.setProperty("SelectionNamespaces",
"xmlns:dfs='http://schemas.microsoft.com/office/infopath/2003/dataFormSolution'
xmlns:tns='http://tempuri.org'
xmlns:my='http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-01-30T22:22:25'");

oWebService.Query();

var oResponse =
oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetMyProfileResponse");
}

I redeclared the "my:" namespace just in case.
This all appears to work correctly and I can programmatically confirm that
the oResponse variable isn't null. However, I can't seem to pull any data
from it.

I've attempted XDocument.UI.Alert(oResponse); but it gives a type:mismatch
error (I'm assuming that oResponse isn't a string).

I have attempted the following code to retrieve just one value, but I think
the namespace prefix is what's keeping this from working:

var oAccount = oResponse.selectSingleNode("//s0:AccountName");

All this code does is return a "'null' is null or not an object" error
(which is the error I would get if I put in any old garbage name for a node.
I have also attempted "//my:AccountName", "//dfs:AccountName", and
"//tns:AccountName" just in case the variable picked up its namespace from
the web service, but all of them return the same error.

So, my guess is that because I'm not specifying the correct namespace
prefix, it can't find the AccountName data in oResponse?
 
S

S.Y.M. Wong-A-Ton

Try checking the string returned by oWebService.DOM.xml. It should contain
all the namespaces that are being used. You could then use this information
to retrieve the nodes you need.

So put the following in your code and take things further from there:

XDocument.UI.Alert(oWebService.DOM.xml);
 
D

DGibson

I've gotten the output and found that the Web Service is returning no prefix
at all. The schema looks like this:

<dfs:myFields
xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:tns="http://tempuri.org/">
<dfs:queryFields>
<tns:GetMyProfile>
</tns:GetMyProfile>
</dfs:queryFields>
<dfs:dataFields>
<GetMyProfileResponse xmlns="http://tempuri.org/">
<GetMyProfileResult>
<PreferredName>data</PreferredName>
<AccountName>data</AccountName>
<WorkEMail>data</WorkEMail>
<WorkPhone>data</WorkPhone>
<ProfileUrl>data</ProfileUrl>
<EmployeeNumber/>
<Department/>
<Title/>
<Manager>data</Manager>
</GetMyProfileResult>
</GetMyProfileResponse>
</dfs:dataFields>
</dfs:myFields>

I've attempted to query this by using:
var oResponse =
oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/GetMyProfileResponse");

This still returns a null error when I attempt:
var oAccount = oResponse.selectSingleNode("AccountName");

Unfortunately, I'm very new to Infopath and Sharepoint, so I'm not sure
where to go from here.
 
S

S.Y.M. Wong-A-Ton

If you look closely, you will see that there is a namespace defined on
GetMyProfileResponse:

<GetMyProfileResponse xmlns="http://tempuri.org/">

See the xmlns definition behind GetMyProfileResponse? If you look at the
namespaces defined under dfs:myFields, you will see that the prefix "tns" was
defined for "http://tempuri.org":

xmlns:tns="http://tempuri.org/"

So to retrieve GetMyProfileResponse, you would have to use something like:

var oResponse =
oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetMyProfileResponse");

Just for fun, add the following line to your code and see what it returns:

XDocument.UI.Alert(oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetMyProfileResponse").xml);

By studying the result, you will know that you would have to retrieve
AccountName as follows:

var oAccountName =
oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetMyProfileResponse/tns:GetMyProfileResult/tns:AccountName").text;

If you want to know all about the use of namespaces in XML, check out the
following document: http://www.w3.org/TR/xmlschema-0/

There is no need to have nightmares over namespaces, and it's okay to be new
to InfoPath and Sharepoint. :)
 
S

S.Y.M. Wong-A-Ton

I've gotten the output and found that the Web Service is returning no prefix

Remove the definition you added earlier for the "my" namespace from your
code. I spotted that you are missing a space behind "
xmlns:tns='http://tempuri.org' " in the oWebService.DOM.setProperty(...)
method. That could be the culprit.
 
D

DGibson

I appreciate the assistance so far, but I'm still having problems.

I've already removed the extra "my:" namespace declaration, so that line now
only says: oWebService.DOM.setProperty("SelectionNamespaces",
"xmlns:dfs='http://schemas.microsoft.com/office/infopath/2003/dataFormSolution'
xmlns:tns='http://tempuri.org' "); (I inserted the space at the end just in
case).

I went back to the Status Report example (which works fine) and inserted the
"XDocument.UI.Alert(oWebService.DOM.xml);" line and the output is the same
schema and namespaces that I was getting back from my form. This is strange
though because the example's code redeclares the tempuri.org namespace with a
"s0" prefix and that example works just fine:
oWebService.DOM.setProperty("SelectionNamespaces",
"xmlns:dfs='http://schemas.microsoft.com/office/infopath/2003/dataFormSolution' xmlns:s0='http://tempuri.org/'");

Taking the example code and replacing "s0" with "tns" just brings me back to
the "'null' is null or not an object" error.

I also attempted to insert the following line:
XDocument.UI.Alert(oWebService.DOM.selectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetMyProfileResponse").xml);
This line returns an error of "Object required".

I feel like I understand namespaces a little better, but I still can't point
out why the one form works and the other doesn't.
 
S

S.Y.M. Wong-A-Ton

The only thing I can advise you is to save your InfoPath form locally on
disk, open it in Notepad, and study its XML structure to see where you might
be going wrong. You can also download a tool called "Visual XPath" from
http://weblogs.asp.net/nleghari/articles/tools.aspx, load the XML from the
InfoPath form into it, and type in XPath expressions to find the correct one
to retrieve the nodes you require.
 
D

DGibson

Visual XPath was exactly what I needed. I was able to get the proper XPath
to the node I wanted and the code now works as intended.

Many thanks!

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top