Parsing Repeater XML


Badge +5

Hi,

I've been trying to read repeater xml following Vadim's blog at  http://www.vadimtabakman.com/nintex-formsworkflow-parsing-repeating-section-data.aspx but I can't get it work correctly.

For test I have 3 fields - txtFirstName, txtLastName and txtAge (numeric)

The repeater is called repTest

I query get the FormData and use the inline function fn-XMLDecode and set it to a variable that I would then like to use XML Query on.

When I query that variable I can only seem get results if I use //repTest     (which is the name of the repeater control)

If I use any other XPath expression I don't get any results. (with the exception of node() and //*)

example:

Form Data
<?xml version="1.0" encoding="utf-8"?><RepeaterData><Version /><Items><Item><txtFirstName type="System.String">first</txtFirstName><txtLastName type="System.String">last</txtLastName><txtAge type="System.Int32">11</txtAge></Item><Item><txtFirstName type="System.String">first2</txtFirstName><txtLastName type="System.String">last2</txtLastName><txtAge type="System.Int32">22</txtAge></Item></Items></RepeaterData>

Decoded Form Data
<?xml version="1.0" encoding="utf-8"?><RepeaterData><Version /><Items><Item><txtFirstName type="System.String">first</txtFirstName><txtLastName type="System.String">last</txtLastName><txtAge type="System.Int32">11</txtAge></Item><Item><txtFirstName type="System.String">first2</txtFirstName><txtLastName type="System.String">last2</txtLastName><txtAge type="System.Int32">22</txtAge></Item></Items></RepeaterData>

//repTest
firstlast11first2last222

//repTest//txtFirstName


//repTest/*

I've tried variations with //RepeaterData/Items/Item etc. (as per the xpath builder)

I've also tried just running a query on  the decoded xml document (just pasted the xml shown in "Decoded Form Data into the XML Query source) and XPath like //txtFirstName. This works fine.

I'm assuming I'm missing an in between step to get the XML properly formatted. I thought I was doing that by using the build string action and fn-XMLDecode but I'm not having any luck with it.


23 replies

Userlevel 5
Badge +9

If you want to use the Query XML action, your XML has to look like the one you posted under Decoded Form Data.

You can use this formula to get the XML of each line of your repeating section in a collection variable (return results as Outer XML) :

//Item

You can then loop through each line (via executing a foreach action on your collection variable) and query the XML of each line to get the value of the fields with this formula (return results as Text):

//TheNameOfTheControlInsideYourRepeatingSection

You can also connect your repeating section to a multi line column and then the XML will be stored in this column (you won't need to read the FormData column and extract the part corresponding to your repeating section).

Hope this helps

Badge +5

Thanks Caroline,

I have since been able to iterate through the items using the multi line plain textbox. I just couldn't get any xpath to work on the form data other than the //repeaterControlName. (i.e. I could not get //Item, //repeater//Item, //controlInsideRepeater, etc. to work)

I will use that for now and look into what I'm doing wrong afterwards.

I also noticed that some xpath functions error out - count(//Item). I'm using xslt to accomplish what I need but xpath less typing happy.png. Will these functions ever be implemented? (or is it that I'm just using them incorrectly)

Userlevel 5
Badge +12

Hi Jan,

I've actually seen that before too when using Form Data directly.   I usually go straight to the multi-line text now since it seems to be more consistent and has never had that issue.

-Mike

Badge +4

Thanks Caroline! That was very helpful. I haven’t found many posts that are detailed in how to properly use the “For Each” and “Collection” variable.

For anyone else reading this, here’s a little more information building on what Caroline said, and is how you might create a For Each workflow that parses the XML. These steps are in the order that you should add the workflow actions with “Set variable” being at the top of the workflow workspace sequence.

  1. Add a “Set variable” action and set a multi-line variable (e.g. “MLOT_XMLDump”) Equals Value [insert your list item XML field which is populated from the repeating section being Connected To it in Nintex Forms Designer].
  2. Create a “Build String” action immediately below with Text being fn-XmlDecode({WorkflowVariable:MLOT_XMLDump}) and Store result in MLOT_XMLDump. This is to remove strange characters from the XML.
  3. Create a “Query XML” action where the XML field is {WorkflowVariable:MLOT_XMLDump} and the Output 1 formula is //Item, and where “Store result in” is your new collection variable (e.g. Collection_Item).
  4. Create a “For Each” action where the “Target collection” is your collection (e.g. Collection_Item) and Store result in is MLOT_Item (a new multiline variable).
  5. Within the “For Each” action, for XML put {WorkflowVariable:MLOT_Item}, for Output 1 set the formula to //TheNameOfTheControlInsideYourRepeatingSection and Store result in (yourNewVariable). Add as many Outputs as you'd like.
  6. Now you have your variables containing the XML values, and you can now add for example an "Update Item" or "Set field value" action to update values in a list item as needed.

A couple other posts on using “For Each” and a “Collection” variable are below. For Each is the fastest method to parse the XML (except if you somehow use client-side Jquery instead):

https://community.nintex.com/message/26604#26604

https://community.nintex.com/message/16949#16949

This one suggests a “Loop” (which can be very slow if you have safe looping enabled):

http://www.vadimtabakman.com/nintex-formsworkflow-parsing-repeating-section-data.aspx

Userlevel 7
Badge +11

Hi Allan,

fair call on the Loop being slow when Safe Looping is enabled.  I don't know what that guy was thinking in that blog post happy.png

You could instead use the Query XML action to pull out all the details into Collection variables, then parse them with a For Each action, that doesn't get affected by Safe Looping.

I have been doing that more and more, since it's pretty easy to parse related collection variables : Nintex Workflow - Iterate through Related Collections - Vadim Tabakman

Vadim

Userlevel 5
Badge +9

Hi Allan,

I'm glad I could help.

Don't hesitate if my explanations are not clear enough wink.png.

Thanks for adding details, it will help the community.

Have you tested without the first two steps you've written and in the "Query XML" action, directly add the reference to the item column connected to your repeating section? (I've alway do that without your first two steps)

Vadim is absolutely right : with his method you will only have one "Query XML" action and one "For each" action.

Badge +4

Thanks Caroline, I'll have to try it again sometime without the first two steps. I ran into an issue where the XML was encoded with extra characters which caused the XML parsing to fail and so it broke my workflow. I then used fn-XmlDecode() which fixed the issue. I had to follow the "Parse that XML" recommendation in the following blog post (and I generally applied this blog post anyway): Best Practices with Repeating Sections in Nintex Forms

Userlevel 5
Badge +9

Great that you could fix your workflow !

Tell me if you have other issues.

Badge +5

Mandeep,

Did you ever find a resolution to the dilemma. I ask, because I see the same issue. I will be trying to figure it out, but if you have a resolution that would be fantastic.

Badge +2

Has there been a resolution to this? I also have this issue.

Badge +5

Don't know if this is the correct answer (as I am still new and learning), I essentially used the suggestions from Allan Nevala, Caroline Jung, and Vadim Tabakman.

The twist for me was using a Regular expression actions. So it goes as follows:

I created Set Variable

  •    Clicked Variables and created my "SPMXMLDump" variable
    • I set it to equal the item list, in my case was Serial_Numbers_of_SPM

SetVariableSPM

I then used the Build String action and used the:

  • fn-XmlDecode(insert variable here)
    • and stored the result, in my case vSMPXMLDump(from our creation of variable and set variable)

BuildStringXMLDecode

Next I used the Query XML action

  • Set XML Source to XML
  • Set XML to, {ItemProperty:SerialNumbersOfSPM}(in my case the item from the list)
  • Set the Output 1 to:
    • Process Using XPath
    • and grabbing the item in the xml of //SerialNumbersOfSPM
  • Set Return results as: to Inner XML
  • Set Store Result in*: to my Collection variable(vSPMCollItem), which I created when setting up the first variable.

BuildQueryXML

Then I used a Regular Expression action

  • Set Pattern to ; (that's a semi-colon)
  • set Operation to Replace Text
  • Set Input Text to my workflow variable, {WorkflowVariable:vSPMCollItem}
  • set Store results in to another variable I created in the beginning called vSPMItems

RegEx

To test, I added the Log in history List action and set it to {WorkflowVariable:vSPMItems}

LogToHistory

Since this worked I then updated my list item using the action Update Item

  • Set Update to use Current Item
  • Select my list item, in my case was Serial Numbers of SPM, and
    • set Equals to value of my variable, in my case, vSPMItems

UpdateSPMItems

Don't forget to end with a Commit Pending Changes action

Any comments or constructive criticisms is always welcomed....Only way we learn more

Userlevel 5
Badge +9

Hi Pete,

Thanks for sharing this !

I read the complete post again and I don't fully understand what you wanted to do. The original question was related to read values in a repeating section field from a workflow. Do you try to update values stored in the XML of a repeating section?

Badge +5

‌ you are correct it was about reading values in a repeating section, when I performed what was mentioned and Mandeep as well performed the available methods we both ran into an issue where when parsing out the xml value it would only write the last value to the list. Hence, in the process of waiting for a reply from Mandeep, I continued to hash out the problem and found a fix in order to take ALL values parsed and put them in the multiline input so that we were not just getting last value write.

Userlevel 5
Badge +9

ok, I understand now wink.png.

I think that the incorrect behaviour (value overwritten) was due to a missing action inside the "For Each". The "For each" action iterates as many times as there are rows in your repeating section. For each row in the repeating section, the value of the control is extracted by the "Query XML" action which is inside the "For Each". If the value extracted from one row is not concatenated to previous values extracted, you will only see the value in the last row of the repeating section. So, after the "Query XML" action which is in the "For each", you need to add a "Set variable" or "Build string" action to concatenate the extraction with previous extractions.

In other words, create a text variable named "txtAllValuesParsed", for example, which will contain all the values separated by a blank space and inside the "For each", after the "Query XML", add a "Build string" action configured as following (assuming that you store the result from the "Query XML" action in a variable named "txtValueExtracted") :

  • Text : {WorkflowVariable:txtAllValuesParsed} {WorkflowVariable:txtValueExtracted}
  • Store result in : txtAllValuesParsed

But your method is easier and quicker if you only want to extract values of one control from a repeating section.

Hope this helps you understand Allan's method

Badge +2

Caroline, Thank you for this post!  I've been racking my brain for days playing with regular expressions trying to get them just right, with your post, it's working like a charm.  Thanks so much!

-Katie

Userlevel 5
Badge +9

Thanks Katie ! I'm really glad that this post could help happy.png !

Badge +4

Thank you for the information.

I get most of it to work but it skips over my For Each.

I am new to this but I think if my xml hase rows in it it should run. I placed a history in there stating "in loop" and one after. I get the after but not the in. In my status I do not get an error and everything is green except for my For Each. It remains white. Not sure my XML is correct but it has extras in there that I am not sure should be there or not.

Detailed history of this workflow.
Action History
ActionStartEndDuration
Log in history list11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
For each11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
For each11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Log in history list11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Set field value11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Query XML11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Build string11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Set variable11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes
Action set11/7/2017 4:25 PM11/7/2017 4:25 PM0 minutes

Task History

Workflow Messages
TimeEventMessageOutcome
11/7/2017 4:25 PMWorkflow CommentMLOT_XMLDump:<?xml version="1.0" encoding="utf-8"?><FormVariables><Version /><Phone type="System.String">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;RepeaterData&gt;&lt;Version /&gt;&lt;Items&gt;&lt;Item&gt;&lt;RowID type=&quot;Sys 
11/7/2017 4:25 PMWorkflow Commentafter loop

Why does it skip over the "For Each"

Thanks.

Userlevel 7
Badge +11

If it's skipping over the For Each, that suggests that your Collection variable is empty.

Confirm that, and if that is the case, you will need to look at what in your workflow is meant to fill that collection.

Vadim

Badge +4

Thanks for the quick reply. This is right after step 1 when I set the variable. And before I encode it in step 2. I pull the XML with "Form Data"

Workflow Messages
TimeEventMessageOutcome
11/8/2017 8:30 AMWorkflow CommentRight after step 1: <?xml version="1.0" encoding="utf-8"?><FormVariables><Version /><Phone type="System.String">&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&amp;lt;RepeaterData&amp;gt;&amp;lt;Version /&amp;gt;&a 
11/8/2017 8:30 AMWorkflow CommentMLOT_XMLDump:<?xml version="1.0" encoding="utf-8"?><FormVariables><Version /><Phone type="System.String">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;RepeaterData&gt;&lt;Version /&gt;&lt;Items&gt;&lt;Item&gt;&lt;RowID type=&quot;Sys 
11/8/2017 8:30 AMWorkflow Commentafter loop
Userlevel 7
Badge +11

Hey Greg,

I'm not sure what that is showing.  What I'd recommend, is that you use a Collection Operation action and get it to do a "Count".  Then log that value.  That will give you an idea of how many items you have in your collection.  If it's empty for whatever reason, that's why it's not going into the For Each loop.

Otherwise, check the For Each and see if you're reusing an Index value or have something configured in it to Stop Processing.  That could also cause the For Each to not enter.

Vadim

Badge +4

Getting there. BTW - still a newbie. But new seems to advance. Does the For Each need to be incremented with the math operation +1? it seems like it is seeing all 3 rows. 

I have 3 items in my XML.

My counts all remain 0 but the For Each appears to loo 3 times.

Date Occurred
Event Type
User ID
Description
Outcome
11/8/2017 9:59 AMCommentCounts: 0
11/8/2017 9:59 AMCommentRight after step 1: <?xml version="1.0" encoding="utf-8"?><RepeaterData><Version /><Items><Item><RowID type="System.String">1</RowID><BusinessPhone type="System.String">ewrre</BusinessPhone><HomePhone type="System.String">ewrr</HomePhone><Field1 type="Sys
11/8/2017 9:59 AMCommentMLOT_XMLDump:<?xml version="1.0" encoding="utf-8"?><RepeaterData><Version /><Items><Item><RowID type="System.String">1</RowID><BusinessPhone type="System.String">ewrre</BusinessPhone><HomePhone type="System.String">ewrr</HomePhone><Field1 type="System.Str
11/8/2017 9:59 AMCommentHit loop #0 RowID:1
11/8/2017 9:59 AMCommentHit loop #0 RowID:1
11/8/2017 9:59 AMCommentHit loop #0 RowID:1
11/8/2017 9:59 AMCommentafter loop
 

In step one what should I use to get the xml? I have tried Form Data and getting the xml from a connected list. The control is named "Phone". I do not have it listed in my work flow list.

Badge +4

It just was not working for me correctly. But I did find something that helped me sort it out. Not sure what it was exactly. Starting fresh helped. 

Best Practices with Repeating Sections in Nintex Forms | Rightpoint 

Thank you again Vadim, Caroline and Allan. Good stuff.

Badge

Hi Allan I am trying the steps as you explain in your post I am stuck on item 5  may you please elaborate on this step should I insert a query xml action and have the set field with in the for each section? The repeating section is a bit confusing .It would be nice to have an illustrated workflow from start to end with list columns being updated.Most posts I have come across ends with the repeating section data being collected and stored how do I populate the list and have it show in list view.

"Within the “For Each” action, for XML put {WorkflowVariable:MLOT_Item}, for Output 1 set the formula to //TheNameOfTheControlInsideYourRepeatingSection and Store result in (yourNewVariable). Add as many Outputs as you'd like."

Reply