Changing XML Content In SharePoint Library

 by Steve O. Ams, Jr.February 26, 2016 1 minute

I’m usually hesitant to share this type of thing, but when I consider the time it took to set it up, I felt as though this needed sharing.
Let’s say you have a nice, neat InfoPath Web Form template currently deployed, and you make use of parameterized values(drop-downs). Great. Well, whenever content in the display values change, you deal with the dilemma of having content essentially at rest, sitting out there in your form library that won’t update until someone actually goes out and opens the entry and/or or triggers whatever event you use to retrieve those new values to populate to that old entry.
Believe me. I’ve looked around for options, and I’m usually met with things that say open a webdav path and use file system options. You’ll notice on larger libraries that this isn’t an option. I’ve also gone down the hairy rabbit hole of checking out the database to extract the xml as binary and write it back. Bad idea. It’s bad in that you don’t actually capture anything about the file that was accessed, changed, or any real backup against catastrophe — outside of a conventional database backup. If you’re running rights management or any such retention policies, you’d need a bucket of justification in explaining that in an detailed audit scenario… separation of duties …DBA’s being able to access content that really isn’t for them to access.
As a SharePoint Administrator, in the end, you’ll need to go to the files where they are and behave as if you are actually changing these files. Using Powershell was the solution.

<#
.SYNOPSIS
   Replaces or adds text to Infopath library entries.
#>
 
  
$site = get-spsite "http://yoursite"
$web = $site.openweb($yoursubsite)
$folder = $web.Folders["YourFormEntryLibrary"]
$files = $folder.Files
foreach ($entry in $files)
{
    $data = $entry.OpenBinary()
    $encode = New-Object System.Text.UTF8Encoding
    $content = $encode.GetString($data)
    if ($content.Contains("Target Hook Property Search"))
    {
        [xml]$x = $content.Substring(1)
        $x.myFields.Field1 #For Output Confirmation
        $x.myFields.Field2 #For Output Confirmation
        $x.myFields.Field3 = "Assigned Value to Target Field"
        $stream = New-Object System.IO.MemoryStream
        $x.Save($stream)
        $entry.SaveBinary($stream.ToArray())
    }
}

The use of ‘myFields’ in the target fields is simply the form namespace. As you can see, i’m using the default, but check for that when leveraging this method.