In my last post I mentioned a project which required me to move documents from one list to another list in a different farm one folder at a time. Along with that was a requirement to set various field values (metadata) based on patterns in the folder name and/or filename. I needed a reasonably flexible way to accomplish this considering that the client didn't actually have a clue as to what they really wanted the rules to be. I already had a command (gl-replacefieldvalues) which let me set the value of an existing field but it didn't allow me to do it based on the values of other fields and there was not real filtering capability. So I built a new command called gl-setmetadata which allows me to pass in an XML file containing various rules.
There's really not much to the code - the bulk of it is just parsing the XML and figuring out what to do. There's two core methods - the first, ProcessFolder, is responsible for getting the collection of items that should be processed using the provided rules. This is done by using an SPQuery object and passing in the Query XML node if present. The second method, ApplyRule, is called by the ProcessFolder method for each Rule node found in the XML and it is responsible for setting any field data based on the rules.
The core thing to understand with this command is the structure of the input folder and this where things get a little more complicated. I don't currently have an XSD for this (I may create one to aid in validation but I just didn't have the time). So failing a good XSD here's a reasonably detailed example XML file with comments:
Note that I don't claim to be a regular expression expert and I've not extensively tested the regular expressions in the examples above and I know that there are issues with them for more complex data but for the purpose of a simple demonstration they do well enough. The example above will return back all documents in the folder "/documents/sub-folder1" and will set the content type of every item to "Dublin Core Columns". It will then standardize the name of the file (FileLeafRef) so that it only contains "*-English" or "*-Korean" using information in the filename and it will also set the Language field to English or Korean using this same information.
Probably the most important thing to remember when constructing your XML is that you need to use the internal field name and not the display name.
You can also do additional filtering using the command line parameters by restricting whether folders are recursed and by specifying a sub-folder instead of a root list folder. The syntax of the command can be seen below:
C:\>stsadm -help gl-setmetadata stsadm -o gl-setmetadata Updates list field values based on the rules defined in the provided input file. Use -test to verify your updates before executing. Parameters: -url <list folder url> -inputfile <input file containing meta data rules> [-recursefolders] [-quiet] [-test] [-logfile <log file>]
Here's an example of how you would execute this command using the XML shown above as an input:
stsadm -o gl-setmetadata -url http://portal/documents -inputfile c:\metadata.xml -recursefolders -logfile c:\metadata.log
Like many of my commands that do batch updating you can run this command in a test mode by passing in a "-test" parameter.