So, I had been asked to write some code to update an Infopath form’s data as it passed through a workflow. This data was being declared as a column in SharePoint, and we wanted the columns value to update. A long struggle ensued…
Right, so, I started with some code to get a SharePoint column, update the column, and save the changes.
SPWeb myWeb = new SPSite(workflowProperties.SiteId).OpenWeb(workflowProperties.WebId);
SPListItem myItem = myWeb.Lists[workflowProperties.ListId].GetItemById(workflowProperties.ItemId);
myItem.Properties["Column Name"] = "Column Value";
myItem.Update();
This worked a treat – but only for columns defined normally. Columns being read from the form lost their values as soon as the update() function was run.
And that was the problem – the values were being read from the form data, the XML. I had hoped that SharePoint would be clever enough to write back into the XML – it isn’t. Instead, it appears you have to do this by hand…
First, get the SharePoint Listitem
SPWeb myWeb = new SPSite(workflowProperties.SiteId).
OpenWeb(workflowProperties.WebId);
SPListItem myItem = myWeb.Lists[workflowProperties.ListId].
GetItemById(workflowProperties.ItemId);
Then get the File for that ListItem – i.e. the XML data
SPFile myFile = myItem.File;
MemoryStream myInStream = new MemoryStream(myFile.OpenBinary());
XmlDocument myDoc = new XmlDocument();
myDoc.Load(myInStream);
Then make your changes to the XML in here – below is what I did, as an example
XmlNode myRoot = myDoc.DocumentElement;
XmlNamespaceManager xmlNSManager = new
XmlNamespaceManager(myDoc.NameTable );
xmlNSManager.AddNamespace("myNameSpace",
"http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-06-08T14:13:41");
XmlNode myColumnToAlter = myRoot.SelectSingleNode("/myNameSpace:WFTaskForm/myNameSpace:myColumn", xmlNSManager);
myColumnToAlter.InnerText = "This has been changed";
When you’ve finished changing your XML data, save the XmlDocument object back into SharePoint as a file.
MemoryStream myOutStream = new MemoryStream();
myDoc.Save(myOutStream);
myFile.SaveBinary( myOutStream.ToArray());
Took me a ridiculous amount of time to figure all that out. It’s a good job that SharePoint makes it so easy…
Actually, I can see why they did it this way – but throwing an exception when I tried to write to the columns being read from the form would be useful. And maybe some instructions somewhere about how to do this. Still, maybe this will prove useful to someone…
Thanks for your help! Writing back to Infopath xml should be simple, but has proven rather difficult. Your article saved me hours of work!
Thanks for the great post!
What is the NamespaceManager for InfoPath 2007 Form?
“http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-06-08T14:13:41″);”
You can find this from the form itself. I think it’s one of the properties of the .XSN file itself. Try opening the .XSN in Infopath and checking for properties (under the file menu) there.
As you’ve rightly noticed, Infopath creates a unique namespace for your form – based on it’s creation/update date, I think.
(I’m no Infopath expert!)
EDIT: Took a look, and the namespace under the File>Properties isn’t quite right – some colons have been replaced by underscores.
There is some good advice from Madhur – which is how I think I’ve done this in the past, actually (a long, long time ago):
Hi there,
Have anyone experience where the schema has change?
I used the code and the workflow run somehow the InfoPath Schema of the xml file has change.
Regards,
Linda.
Hmm. Sounds weird. Have you updated the Infopath form maybe? I’ve had issues where we’ve updated the Infopath form – versioning on Infopath forms in SharePoint can be a bit hit and miss. We ended up installing our latest version for as an entirely new form…
The code works fine for simple field updates. I tried it for just a text box on a sample form.
But, when I have a Contact Selector on the infopath form I get the dreaded “Schema validation found non-datatype errors”. This is a repeating object that allows the lookup of a person. If I have this control on the page, and I read and save the form (even without an update) I get the above mentioned error. I have read up on the error and most people experience it when they set a nil value to an object and don’t remove the attribute.
Any help is appreciated
When i use the code and change field value in infopath form, which is saved in sharepoint library. The form start giving “Schema validation found non-datatype errors.”
When i compared the old xml with updated xml of the form i found that some of the white spaces has been removed so i make following changes in the code and it worked for me.
XmlDocument myDoc = new XmlDocument();
/// Add this line of code ///
myDoc.PreserveWhitespace = true;
myDoc.Load(myInstream);
I had this issue only when I had an InfoPath form linked to a custom workflow.
The error started to occur when I modified my InfoPath form to have an attachment field. When a custom workflow was associated to my form and I left the attachment field empty, I could not reopen the form without getting the “The form has been closed” error.
I only experienced this problem with the combination of the workflow and the empty attachment field. If I disassociated my workflow from the form, my form wouldn’t show the “The form has been closed” error. If I removed the attachment field, it would work too.
When I saved a filled out form to my desktop and opened it with notepad, I realized that the form had the xsi:nil=”true” field. I removed this attribute, resaved the form, uploaded back to the form library and the form would open up properly.
The myDoc.PreserveWhitespace=true; worked!
Great work, Save a lot of time.
I have an issue with the code
after I say
myDoc.Save(myOutStream);
myFile.SaveBinary( myOutStream.ToArray());
it invokes the workflow again instead of going to the next step in the code?
Any idea on how to stop the loop?
hi guys
i have a problem
When update a field of a item XML (Infopath Form in Sharepoint Library) by code of C#, with the you code indicate on top; and then i trying to open this item of my sharepoint list… give me the following error: the form contains schema validation error…
Details:
Element ‘{http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}sec_SafendOptions’ is unexpected according to content model of parent element ‘{http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}myFields’.
Expecting: {http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}sec_WaiReqInf, {http://schemas.microsoft.com/of….
I need youre help please
Regards
hi guys
i have a problem
When update a field of a item XML (Infopath Form in Sharepoint Library) by code of C#, with the you code indicate on top; and then i trying to open this item of my sharepoint list… give me the following error: the form contains schema validation error…
Details:
Element ‘{http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}sec_SafendOptions’ is unexpected according to content model of parent element ‘{http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}myFields’.
Expecting: {http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-02-02T22:15:26}sec_WaiReqInf, {http://schemas.microsoft.com/of….
I need youre help please
How to resolve?
Regards
Where was this article 3 days ago when i needed it?!! LOL Thanks so much. Just saved my project.
Old post but still relevant. You can create the namespace manager from the XML document itself and avoid issues with the schema changing:
private XmlNamespaceManager CreateNamespaceManager(XmlDocument doc)
{
XPathNavigator nav = doc.CreateNavigator();
nav.MoveToFollowing(XPathNodeType.Element);
IDictionary namespaces = nav.GetNamespacesInScope(XmlNamespaceScope.All);
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
foreach (string key in namespaces.Keys)
{
manager.AddNamespace(key, namespaces[key]);
}
return manager;
}