UpdateListItems: Parsing special characters

Coordinator
Jul 19, 2011 at 5:37 PM
Edited Jul 19, 2011 at 5:39 PM

From comments on http://spservices.codeplex.com/workitem/8632, written by Srividya on Mon at 10:24 PM

Hi Marc,

I am adding the query to codeplex for your review. I have attached the basic updatelistitem code. I could not figure out where to modify the above mentioned codes.

*I am setting up a simple initiative management system where users can upload documents into specific folders. The folder structure is predefined and cannot be modified by end user. So when a user creates a new initiative, the entire folder structure for the initiative is created using UpdateListItem. I also passed metadata to folder(a content type -folder with category) itself with initiative name so I can filter and display only relevant folder for the specific initiative.

I've then created a left navigation from where the query string value is passed to the document library.

So now if the initiative name contains special characters, folder does not get created. Also when the initiative name contains "+", the folders get created but I am unable to access them via left navigation as the "+" does not get encoded.

I hope this helps! I have attached a screenshot as well

Reference - NBSP

Parse special characters


Hi Marc,

I could get the above working. Thank you very much!

Now I seem to have an issue when the Title column contains special characters. There are 2 places where I face an issue.

When calling UpdateListItems - if the Title column contains special characters (example "/") it does not work. I checked the codeplex solution but I dont know where to add the code or change it to work for "/".

http://spservices.codeplex.com/workitem/8632

The query string variable - I noticed that when the query string variable contains "+" the filtered page does not load with the necessary details. However, the UpdateListItems call is made correctly.

I checked that there is a javascript to replace + with a space but I need the + to show as +.

Kindly help and thanks in advance for your time and support.

Regards,
Srividya

 

<script language="javascript" type="text/javascript" src="../../Scripts/jquery-1.5.2.min.js"></script>
<script language="javascript" type="text/javascript" src="../../Scripts/jquery.SPServices-0.6.1.min.js"></script>
<script language="javascript" type="text/javascript" >
function PreSaveAction() {
var titleColumnValue = $("input[Title='Initiative Name']").val();
$().SPServices({
   operation: "UpdateListItems",
   async: false,
   listName: "Initiative Documents",
   updates: "<Batch>" +
     "<Method ID='1' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "</Field>" +
      "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>BASE</Field>" + "</Method>" +
"<Method ID='2' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Base Plan_FCR_IFS" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Base Plan_FCR_IFS</Field>" + "</Method>" +
"<Method ID='3' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/CPS_Accelerator Report" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>CPS_Accelerator Report</Field>" +
"</Method>" +
"<Method ID='4' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/GTRO_Technical Risk Assessment" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>GTRO_Technical Risk Assessment</Field>" + "</Method>" +
"<Method ID='5' Cmd='New'>" + "<Field Name='ID'>New</Field>" + "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Initiative Announcements_Post Launch Tracking" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Initiative Announcements_Post Launch Tracking</Field>" + "</Method>" +
"<Method ID='6' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Pre-TTR_TTR_Toolbox" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Pre-TTR_TTR_Toolbox</Field>" + "</Method>" +
"<Method ID='7' Cmd='New'>" +  "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Decision Sheets_Change Management_PACE" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Decision Sheets_Change Management_PACE</Field>" + "</Method>" +
"<Method ID='8' Cmd='New'>" + "<Field Name='ID'>New</Field>" + "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Project Knowledge" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Project Knowledge</Field>" + "</Method>" +
"<Method ID='9' Cmd='New'>" +
      "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/SIMPL Working Documents" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>SIMPL Working Documents</Field>" + "</Method>" +
"<Method ID='10' Cmd='New'>" + "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Meeting Notes_Key Project Events" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Meeting Notes_Key Project Events</Field>" + "</Method>" +
"<Method ID='11' Cmd='New'>" + "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Consumer_Technical Research" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Consumer_Technical Research</Field>" + "</Method>" +
"<Method ID='12' Cmd='New'>" + "<Field Name='ID'>New</Field>" +
      "<Field Name='ContentType'>Folder with Category</Field>" +
      "<Field Name='BaseName'>" + titleColumnValue + "/Marketing Concept_ZMOT_FMOT_SMOT" + "</Field>" + "<Field Name='Initiative_Name'>" + titleColumnValue + "</Field>" + "<Field Name='Document_x0020_Category'>Marketing Concept_ZMOT_FMOT_SMOT</Field>" + "</Method>" +
"</Batch>",
   completefunc: function(xData, Status) {
       }
  });
return true;  
} 
</script>
Coordinator
Jul 19, 2011 at 5:45 PM

Srividya:

You can probably fix this easily by simply escaping the problem value. It looks like you are only using one value from the titleColumnValue variable.

M.

Jul 19, 2011 at 11:10 PM

This script would be an ideal candidate to use my new roboCAML project.  It will write all of the CAML for you, so you don't have to worry about properly escaping values...

It's still in Alpha, but that's because I've been slacking on the documentation.  If you are interested, I'd love to hear what you think.

 

Cheers,

Matt

Coordinator
Jul 19, 2011 at 11:12 PM

So how would you escape the values in the CAML that your roboCAML project would produce?

M.

Jul 20, 2011 at 2:14 PM

Marc,

I looked for code in JS to escape the characters before i approached you.  I tried dropping this code in a CEWP with PSEncodeString replaced with the query string parameter name (IName in my case) Should this be titleColumnValue variable?

Also the first sentence below states that i need to call the URLEncode() with a string argument but I could not figure out how to actually add it.

Basically I don't think I understand the code below and know how to add it to the page and call these functions.

Thank you for your time. I really appreciate your help.
Srividya

==============

From the blog

I wrote this tiny function so you can include it on any ASP page with any scripting language and use it. Just include it in any ASP page and call the function URLEncode() with a string argument.

<script language=JavaScript RUNAT=SERVER>
// This function decodes the any string
// that's been encoded using URL encoding technique

function URLDecode(psEncodeString)
{
  return unescape(psEncodeString);
}
</script>

For "+"  see comment below

Some people have asked me how to decode those "+"s, which are nothing but encoded spaces in the URL. Although Request.QueryString("your_key") should remove the +s, here is the code that will replace +s with spaces.

<script language=JavaScript RUNAT=SERVER>
// This function decodes the any string
// that's been encoded using URL encoding technique

function URLDecode(psEncodeString)
{
  // Create a regular expression to search all +s in the string
  var lsRegExp = /\+/g;
  // Return the decoded string
  return unescape(String(psEncodeString).replace(lsRegExp, " "));
}
</script>

===================================

Matt - I did visit the link you provided and its interesting. The instructions were complex for me to follow at my level of knowledge with SharePoint. Is there a simpler more real world example implemented that I can see and then reapply?

Thanks again for your help.
Srividya

Coordinator
Jul 21, 2011 at 1:41 PM

Srividya:

I just did a quick test with UpdateListItems and updated the Title of an item to "This / That", which worked fine: no errors. So there must be some other issue. You can't have a slash in a folder name, of course! Folders are delimited in URLs with slashes, so that's a no-no.

As for the "+" characters, can you tell me a bit more about this issue? How are you trying to use the Query String value and what is happening that you don't expect?

M.

Jul 21, 2011 at 6:09 PM

Hi Marc,

Thank you for trying out! In my set up, I have a list where I create the initiative and then the folder structure gets created with the main folder name same as the initiative name.

So I understand now that an initiative name with a / will get created in a list but since folder name cannot have / it will not work.

Is there a better way of doing this set up and not have the limitations? like when the initiative name contains a / i replace the folder name with an "_" or something?

For +

  1. When the initiative name contains + sign, in the backend the folder structure is getting created as it does not have /.
  2.  However when I click the left navigation, I see the same empty page as #3. Query string URL - sites/InitiativeWorkspace/Shared%20Documents/NewHome.aspx?IName=Test%20++

PS - I read on blogs that SharePoint reads spaces as + in query string. I however want the + to be read as + and show the corresponding folder structure. I don't know how to do that.

I hope this makes sense. Thank you again for your time and my apologies if I am not able to express clearly.

Have a good day!

Srividya

 

 

Coordinator
Jul 21, 2011 at 6:33 PM
Edited Jul 22, 2011 at 4:20 AM

I think in my example (the articles you found of mine), I replaced slashes with dashes or something. It's a simple matter of using some value character instead of the slash.

So on the "+" thing, your initiative names contain the "+" character? It's probably basically the same issue. You can replace them with something else.

M.

Jul 22, 2011 at 12:20 AM
Edited Jul 22, 2011 at 12:26 AM

Reading over the problem, I definitely jumped the gun. :P  I saw a bunch of code that is prime time ready to use roboCAML.  Here's what I mean.  Using roboCAML, your updates string would look like this:

 

 

var titleColumnValue = 1;
var updates = roboCAML.BatchCMD({
	//Mandatory parameter
	batchCMD: "New",
	//Mandatory parameter
	valuePairs: [	//Static Column Name, Value
			["ContentType", "Folder with Category", "BaseName", titleColumnValue, "Initiative_Name", titleColumnValue, "Document_x0020_Category", "BASE"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Base Plan_FCR_IFS", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Base Plan_FCR_IFS"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/CPS_Accelerator Report", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "CPS_Accelerator Report"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/GTRO_Technical Risk Assessment", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "GTRO_Technical Risk Assessment"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Initiative Announcements_Post Launch Tracking", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Initiative Announcements_Post Launch Tracking"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Pre-TTR_TTR_Toolbox", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Pre-TTR_TTR_Toolbox"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Decision Sheets_Change Management_PACE", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Decision Sheets_Change Management_PACE"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Project Knowledge", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Project Knowledge"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/SIMPL Working Documents", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "SIMPL Working Documents"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Meeting Notes_Key Project Events", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Meeting Notes_Key Project Events"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Consumer_Technical Research", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Consumer_Technical Research"],
			["ContentType", "Folder with Category", "BaseName", titleColumnValue + "/Marketing Concept_ZMOT_FMOT_SMOT", "Initiative_Name", titleColumnValue, "Document_x0020_Category", "Marketing Concept_ZMOT_FMOT_SMOT"]
		]
});

 

That would result in a string just like yours without the <Field Name='ID'>New</Field>:

 

<Batch OnError='Continue'><Method ID='1' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>BASE</Field></Method><Method ID='2' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Base Plan_FCR_IFS</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Base Plan_FCR_IFS</Field></Method><Method ID='3' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/CPS_Accelerator Report</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>CPS_Accelerator Report</Field></Method><Method ID='4' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/GTRO_Technical Risk Assessment</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>GTRO_Technical Risk Assessment</Field></Method><Method ID='5' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Initiative Announcements_Post Launch Tracking</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Initiative Announcements_Post Launch Tracking</Field></Method><Method ID='6' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Pre-TTR_TTR_Toolbox</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Pre-TTR_TTR_Toolbox</Field></Method><Method ID='7' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Decision Sheets_Change Management_PACE</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Decision Sheets_Change Management_PACE</Field></Method><Method ID='8' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Project Knowledge</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Project Knowledge</Field></Method><Method ID='9' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/SIMPL Working Documents</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>SIMPL Working Documents</Field></Method><Method ID='10' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Meeting Notes_Key Project Events</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Meeting Notes_Key Project Events</Field></Method><Method ID='11' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Consumer_Technical Research</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Consumer_Technical Research</Field></Method><Method ID='12' Cmd='New'><Field Name='ContentType'>Folder with Category</Field><Field Name='BaseName'>1/Marketing Concept_ZMOT_FMOT_SMOT</Field><Field Name='Initiative_Name'>1</Field><Field Name='Document_x0020_Category'>Marketing Concept_ZMOT_FMOT_SMOT</Field></Method></Batch>

 

There are some other benefits built in a well, like building dynamic CAML queries.  I'm getting the documentation sorted right now, but I definitely think it would be helpful here.  Just not with the original problem.  Sorry about that. :P

 

Cheers,

Matt

Aug 1, 2011 at 2:10 PM

Hi Marc,

I understand now. I will look up the code and see if I can replace it with a different character yet retaining the functionality.

I have a different question though not related. Is it possible to create a new discussion board for every initiative using SPwebpservices? We would like users to be able to discuss/email items related to initiatives. Eager to hear if this is feasible.

Thanks again for your help.
Srividyta

Coordinator
Aug 1, 2011 at 2:28 PM

Srividyta:

You could create a new thread in an existing Discussions list using UpdateListItems.

M.