Use Find/Replace in PowerShell to fix InfoPath Forms after moving to a new Site Collection


I know I know, that’s a really long title.

I found some pretty good PowerShell how-to’s which described how to use Get-ChildItem to iterate through a folder – checking each item for a string and then using -replace to fix the string.

However, my situation was slightly different as I wanted to walk through a SharePoint 2010 Form Library – fixing InfoPath forms which had been moved into a new site collection and thus did not open in the browser and would not save due to the old reference to the XSN.

I’m sure there may be better methods on moving XSNs and XMLs across site collections where maybe this wouldn’t be necessary, but if you’re reading this I’ll assume you don’t care.

In any case, what I ended up doing (after obviously re-publishing the XSN template to the new site collection so new IP forms wouold work) is:

  1. Copy all of the forms using Windows Explorer (we didn’t care about versions or modified by metadata, just the content type metadata) into the new Form Lib.
  2. Run the following PowerShell code to fix each XML file – replacing the link to the old XSN with a link to the new XSN (Note: I ran this on my desktop, NOT on the server as I didn’t need any SP cmdlets):
$files = Get-ChildItem \\sitecollection\davwwwroot\FormLib -Filter "*.xml"
foreach ($file in $files) {
(Get-Content $file.fullname) | ForEach-Object {$_ -replace "http://sitecollection/library/OLDXSNPATH.xsn", "http://newsitecollection/library/NEWXSNPATH.xsn"} | Set-Content $file.fullname
}

Voila, all IP forms are now fixed and will not only open in the browser as expected – but I can now update these forms in the new location as they now point to the correct XSN template.

If you’re a frequent reader you’re probably thinking “Wow, normally he gives us these nice functions with parameters, help, etc.”… You’re right, this time it was a quick and dirty chunk of code. However, chances are I’ll need to do this again – so I did actually write a function for future needs:

function Reset-InfoPathTemplateLink {
Param(
[string]$FilePath,
[string]$FileExtension,
[string]$OldPath,
[string]$NewPath
)
$files = Get-ChildItem $FilePath -Filter $FileExtension
	foreach ($file in $files) {
		(Get-Content $file.fullname) |
		ForEach-Object {$_ -replace $OldPath,$NewPath} |
		Set-Content $file.fullname
	} #end foreach
} #end function

To run the function, first dot-source it and then use the following syntax:

Reset-InfoPathTemplateLink -FilePath "\\sitecollection\subsite\formlib" -FileExtension "*.xml" -OldPath "http://sitecollection/doclib/template.xsn" -NewPath "http://newsitecollection/newdoclib/newtemplate.xsn"

As always, happy PowerShelling!

5 thoughts on “Use Find/Replace in PowerShell to fix InfoPath Forms after moving to a new Site Collection

  1. Mike Tupker (@mtupker)

    First off, awesome idea. I used this on a migration we did for a library. I did run into a problem. On some of the forms (xml files) it appears that in some files a double space exists. after the script did it’s string replace thing, one of the spaces was replaced by a very strange character/text. It look like “xAO” highlighted in black. Did you ever run into that? I’m guessing it’s something with the encoding flag with the set-content cmdlet, but I’m not sure what to set it to. any thoughts?

  2. Mike Tupker (@mtupker)

    Actually I found out what that charater is, it’s a non-breaking space. http://en.wikipedia.org/wiki/Non-breaking_space. I’m still looking for a powershell solution, however I’ve found that notepad++ has a “Find in Files” feature (ctrl-F). you can specify a old string and a new string along with a directory. Then click on the replace in files button. It seems to be able to go through and replace the strings with the new URLs while ignoring the non-breaking space character. I’m going to test it a little more tonight. For now this is a good enough work around for me.

    • Ryan Dennis

      Mike,
      Thanks for the comments! I’m glad you found that it was a non-breaking space. I do not recall running into that issue, but it has been a while since I used this solution. I would be curious to know what you find.

      Thanks!
      Ryan

  3. Mike Tupker (@mtupker)

    I found an old blog post buried in the google cache that seems to indicate that the non-breaking spaces may have been introduced by an issue with the multi-line text box long ago. http://webcache.googleusercontent.com/search?q=cache:vvcuRUjful0J:geek.hubkey.com/2007/10/multi-line-text-box-and-its-malcontents_18.html+&cd=1&hl=en&ct=clnk&gl=us. I the forms we have are up to 2-3 years old so it’s possible.

    The main problem I had was trying to figure out how to do a replace on a non-txt complaint character. I found the answer here: http://stackoverflow.com/questions/2162322/join-string-with-non-breaking-space-in-powershell. The post doesn’t directly deal with replacing non-breaking spaces but it does show how to identify them and do a join operation. you have to use [char]0x00A0. Below is what I came up with. It’s really just derivative of the script you posted in the article.

    $FileExtention = “*.xml”
    $FilePath = “C:\XML”

    $files = Get-ChildItem $FilePath -Filter $FileExtension
    foreach ($file in $files) {
    (Get-Content $file.fullname) | ForEach-Object {$_ -replace [char]0x00A0,” “} | Set-Content $file.fullname
    } #end foreach

    This could likely be included in the Reset-Infopathtemplatelink function, however I think the file would have to be saved twice. Since the first save is the one that fixes the URL but creates the issue with xA0, then the second save would do the replace.

    function Reset-InfoPathTemplateLink {
    Param(
    [string]$FilePath,
    [string]$FileExtension,
    [string]$OldPath,
    [string]$NewPath
    )
    $files = Get-ChildItem $FilePath -Filter $FileExtension
    foreach ($file in $files) {
    (Get-Content $file.fullname) | ForEach-Object {$_ -replace $OldPath,$NewPath} | Set-Content $file.fullname #replace URL
    (Get-Content $file.fullname) | ForEach-Object {$_ -replace [char]0x00A0,” “} | Set-Content $file.fullname #fix non-breaking spaces if they exist
    } #end foreach
    } #end function

    I haven’t tested the new version of the function but the first code segment above did work in removing the non-breaking space. I imagine the function will also work though.

  4. Volkan Zihni

    Hi Ryan,

    Is is possible to manually choose the template file location. I’ve recently relinked alle files in a library, but sharepoint does not seem to get the template file location correct.