Sample code for process XML fields

  • 17 August 2005
  • 9 replies
  • 5 views

Badge +5
To my dismay, I could find little documentation on how to interact with process XML fields (DataGrid) via code which is where I plan to store the list of usernames after I call a webservice. I've been basically trying to reverse engineer some code that K2 inserts when one tries to use a data manipulation event. I get various exceptions k2 runtime errors like "the root element is missing..." But I can see a root element in both, removing the lookup into the XML Document still suggests the problem is with the K2 field. Overall, I don't know how to add new rows to k2 process XML fields via code. Is there a decent code sample that can use various properties of this k2 feature?

Here's some code that I was trying to use
.Value, "UserList/userName", aName.InnerXml);
}



(I have been working on addiding destinations from an outside source ( like webservice ) and not something easy like InfoPath. )

9 replies

Badge +9
Xlay, In K2.net Studio, do you have valid metadata specified for the XML Field? If not open the XML Field in K2.net Studio and click on the XML Metadata tab, on this tab you will find a Create a XML Instance button. This function creates valid metadata for the XML Field.

Please let me know if this was helpful.
Badge +5
Rénier thanks for your reply, but after completing your steps I'm still getting the same "The root element is missing" error at runtime. I'm attaching the screenshot [K2 generated XML metadata] of the XML process field and the Metadata. (Since I used a sample XML field to specify the schema, even overwriting it with K2 generated data doesn't work).
Please let me know if it would be helpful for me to send any more material out to solve this problem.
Badge +5
... but it only stores the last value (row) for this column from the XML document. I thought the whole point of XML data fields is to hold multiple rows for the same column...
Badge +9
Hi Xlay,

The result you get from the function in K2Utilities is expected, the function is indented to update the value of the selected node. You need to code the section to add multiple nodes to a repeating section of XML. My advice:

Create the following well defined XML Field containing a repeating node (e.g. Users):


<UserList>
<Users>
<UserName />
</Users>
</UserList>


The following sample code is what you are looking for:

.ToString();
oXmlDoc.DocumentElement.AppendChild(oXmlNode);


Let me know if this is helpful!
Badge +5
Thanks a million! I got your general idea and simply assigned the value of inner xml of my xml document which is formatted in the same way as the UserList/Users.

This works and is great and all, but does this mean that the since the only method that sets XML values is
SourceCode.K2Utilities.XMLFieldMod.SetXMLValue
any complex XML work should be done outside of K2 to format the XML document to be the in the same XML field format in process/activity XML? (Where by complex I really mean something as basic cloning/adding/removing repeating elements/attributes )
Badge +9
Hi Xlay,

..any complex XML work should be done outside of K2 to format .

Not True!

SourceCode.K2Utilities.XMLFieldMod.SetXMLValue is a collection of common methods grouped together as a helper class in K2.net Studio. K2Utilities is typically used by our dev team to accomplish certain manipulation of data specific to the requirements of the templates that ships with K2.net. In your case you need to write your own code to accomplish the needed functionality, K2.net 2003 Studio allows developers to write complex code of any nature by simply adding a Server event or by extending existing template code. No limitation around the number of lines of code implemented in an event, also refer to the Code Module section in the help file. Code Modules acts as a class to the process. This can be used to develop/code common functionality in one place and re-use all over in processes.
Badge +5
I only suggested doing it outisde (or custom classes) because the K2Utilities doesn't bring in a lot of flexibility in its basic methods. I'm OK with writing custom code, but having more extensive built in functionality wouldn't hurt for future releases. Anyways, thanks for all the help!
Badge +9
You are welcome, please shout if you need help!
Badge +3
Hi,

I have an xml document with approvers listed for a workflow. I have a k2smartform that has activity data, I want to map the activity data to my process xml fields. I create an xmldocument and load the xmlfields, i then use the xmlmod to try to update the document and then load that back into the xmlfields. I can't seem to get the update to work. I am posting my code.

public void Main(ServerEventContext K2)
{
string strAction = "";
string xpath = "";
string xpathComment = "";
System.Xml.XmlDocument procXML = new System.Xml.XmlDocument();

try
{
K2.Synchronous = true;
//Update the Process Datafields
K2.ProcessInstance.DataFields["CurrentAction"].Value = K2.ActivityInstanceDestination.DataFields["Action"].Value;

//Get the process xmlfields and put it in an xmldocument
procXML.LoadXml(K2.ProcessInstance.XmlFields[0].Value);

//update the process xmlfields with the Activity Data for this step
//
strAction = K2.ActivityInstanceDestination.DataFields["Action"].Value.ToString();
xpath = "K2DataGridRoot/Item[StepID='CC_BAM'][Approver='THCGTina.Zuffoletti']/Action";
SourceCode.K2Utilities.XMLFieldMod.SetXMLValue(procXML.InnerXml,xpath,strAction);

xpathComment = "K2DataGridRoot/Item[StepID='CC_BAM'][Approver='THCGTina.Zuffoletti']/Comment";
SourceCode.K2Utilities.XMLFieldMod.SetXMLValue(procXML.InnerXml,xpathComment,K2.ActivityInstanceDestination.DataFields["Comment"].Value.ToString());

//Load the updated xml back to the process xmlfields
K2.ProcessInstance.XmlFields[0].Value = procXML.InnerXml;
}
catch (Exception ex)
{
throw new Exception(procXML.InnerXml + " updated process xmlfields" + K2.ProcessInstance.XmlFields[0].Value + " " + ex.Message);
}
}

here is the xmlfields
<?xml version="1.0" encoding="utf-8"?>
<K2DataGridRoot>
<Item>
<Approver>THCGTina.Zuffoletti</Approver>
<Action>
</Action>
<Comment>
</Comment>
<TimeStamp>
</TimeStamp>
<StepID>CC_BAM</StepID>
</Item>
<Item>
<Approver>THCGTina.Zuffoletti</Approver>
<Action>
</Action>
<Comment>
</Comment>
<TimeStamp>
</TimeStamp>
<StepID>CC_Legal</StepID>
</Item>
</K2DataGridRoot>

I am expecting this result
<?xml version="1.0" encoding="utf-8"?>
<K2DataGridRoot>
<Item>
<Approver>THCGTina.Zuffoletti</Approver>
<Action>Approve</Action>
<Comment>Work Item is Approved<Comment/>
<TimeStamp/>
<StepID>CC_BAM</StepID>
</Item>
<Item>
<Approver>THCGTina.Zuffoletti</Approver>
<Action/>
<Comment/>
<TimeStamp/>
<StepID>CC_Legal</StepID>
</Item>
</K2DataGridRoot>

I have looked at all of the data during runtime and find that the K2.ActivityInstanceDestination has the proper values for Action and Comment and the xpath function tested in .net gives me the desired node. I don't know why the update is not occurring.

Thanks,

Reply