Ready to Learn?Ex Libris products all provide open APIs

Tech Blog

 

Using Voyager SIF records to create Alma XML patron load data

So, you've moved to Alma, but your Student or HR system is still providing patron records in Voyager SIF format. We've been using the Voyage SIF format for patron records since implementing Voyager, and so over time developed a PHP include file to allow us to read, generate and write Voyager SIF patron records in a quick and efficient way. At the time of migrating to Alma our Student and HR systems put a feature freeze in place, so that for the moment we're stuck with Voyager SIF records to import. We needed to transform SIF files into XML files that the Alma loader would accept.
 
Basically, how it works for us is that the SIF record is read into a data structure which allows you do all sorts of data manipulation, including cross-walking the patron record into something that will be accepted by the Alma patron record loader interface. The PHP include file handles the bulk of the hassles of working with SIF files, including number of addresses, length of record elements and packing the data with the correct number of spaces.
 
Firstly, you can start by reading the string containing the SIF record into the standard data structure:
 
$patron_record = readsifline($line);
 
This function call reads the string containing the patron record, checks the address count, and uses a built in function from the include file to create a data structure with the correct number of addresses, and then fills in all of the fields with the data from the string padded to the correct format for a SIF record.
Once you've got your patron record, you can access various elements in the record, ie:
 
print $patron_record['patron_registration_date'];
 
How you create the equivalent Alma XML and cross-walk the various SIF fields into their Alma equivalent is up to you. We use SDO_DAS_XML, since that allows you to provide a WSDL file to validate the XML against - ie user_record.xsd with a little modification to work with SimpleType objects.
This means that we can do something like:
 
$xmldas = SDO_DAS_XML::create();
$xmldas->addTypes("xsd/user_record_simpletypes.xsd");
$doc = $xmldas->createDocument();
$rdo = $doc->getRootDataObject();
$userDetails = $xmldas->createDataObject('http://com/exlibris/urm/user_record/xmlbeans','userDetails');
$userDetails->firstName = rtrim($patron_record['first_name']);
$userDetails->middleName = rtrim($patron_record['middle_name']);
$userDetails->status = "Active";
$userDetails->userType = "External";
$userDetails->userName = rtrim($patron_record['inst_id']);

...
 
Using the dates from the SIF record is fairly straight forward - we just need to remove the '.'s in the Voyager SIF record and any trailing spaces
  $userDetails->expiryDate = preg_replace('/\./','',rtrim($patron_record['patron_expiration_date']));
  $userDetails->purgeDate = preg_replace('/\./','',rtrim($patron_record['patron_purge_date']));

...

$rdo->userDetails = $userDetails;
 
The above code creates a XML structure, creates a node for userDetails with some fields from the SIF record, using rtrim to remove the trailing blanks associated with a voyager SIF record field. It then attaches the userDetails node to root of the XML document (patron record) The ... indicates more code before the node is written, and the $rdo command at the end just attaches the node to the XML structure.
In the example below you can attach additional nodes to the userDetails node to specify identifiers
Ie barcodes from the SIF record:
 
$userIdentifiers = $xmldas->createDataObject('http://com/exlibris/urm/user_record/xmlbeans','userIdentifiersList');
  for ($t = 1; $t <= 3; $t++)
  {
  $userident = $xmldas->createDataObject('http://com/exlibris/urm/user_record/xmlbeans','userIdentifier');
  $userident->type = "BARCODE";
  $userident->value = rtrim($patron_record['patron_barcode'.$t]);
...
 
And only add the barcode identifier branch where it wasn't empty and the patron group was valid in the SIF file - ie:
$userIdentifiers->userIdentifier = $userident;

Once you've filled in all of the fields you can, using the Voyager SIF data, and added any additional information, you can then save off the final XML document after ensuring you've attached all the nodes to the XML document in the correct spots. If you've created nodes and not attached them, then they won't be saved to the XML record.

Save the final XML document for the patron record off to a string to allow us to do some cleanup before output:
 
$test_record = $xmldas->saveString($doc,-1);
 
Then clear away the extraneous XML formating to provide a simple and clean XML record to add to the end of the list of user records:
 
$test_record = preg_replace('/ xmlns:tns="http:\/\/com\/exlibris\/urm\/user_record\/xmlbeans" xmlns:xsi="http:\/\/www.w3.org\/2001\/XMLSchema-instance"/','',$test_record);
$test_record = preg_replace('/\<\?xml version="1.0" encoding="UTF-8"\?\>\\n/','',$test_record);
 
Which ends up producing something like:
 
<userRecord><userDetails><status>Inactive</status><userType>External</userType><expiryDate>20160331</expiryDate><defaultLanguage>en</defaultLanguage><userName>TEST</userName><firstName
>Melissa</firstName><lastName>Smith</lastName><middleName>Sheelly</middleName><jobTitle></jobTitle><jobDescription></jobDescription><userGroup>P</userGroup><birthDate></birthDate><purg
eDate>20291231</purgeDate><password></password><pinNumber></pinNumber></userDetails><owneredEntity><modificationDate>20150223</modificationDate><createdBy>SIS</createdBy></owneredEntity><
userNoteList/><userBlockList><userBlock><status>Active</status><type>Cash</type><note>Sanction for outstanding debt from Student System applied 23/02/2015</note><blockDefinitionId>SUSPEND
ED</blockDefinitionId></userBlock></userBlockList><userIdentifiers/><userAddressList><userPhone preferred="false" preferredSMS="true"><phone>0414888888</phone><types><userPhoneTypes>mobil
e</userPhoneTypes></types></userPhone><userAddress preferred="true"><line1>6 Jones Ave</line1><line2></line2><line3></line3><line4></line4><line5></line5><city>WEST CROYDON</city><sta
teProvince>SA</stateProvince><postalCode>5008</postalCode><country></country><startDate>20150220</startDate><endDate>20291231</endDate><types><userAddressTypes>home</userAddressTypes></ty
pes></userAddress><userEmail preferred="true"><email>smith01@flinders.edu.au</email><types><userEmailTypes>personal</userEmailTypes></types></userEmail></userAddressList><userStatistical
CategoriesList><userCategory><statisticalCategory>MRO</statisticalCategory></userCategory><userCategory><statisticalCategory>914</statisticalCategory></userCategory><userCategory><statist
icalCategory>1</statisticalCategory></userCategory><userCategory><statisticalCategory>OD</statisticalCategory></userCategory><userCategory><statisticalCategory>DOC</statisticalCategory></
userCategory></userStatisticalCategoriesList></userRecord>
 
Note, that as part of the building/cross-walking process we've added a block to this patron's record and made them inactive and suspended due to an outstanding fee indication from our Student System.
We've also set the creator of the record to SIS, which is the identifier used by the external interface in Alma that loads the records from our Student System.
It's then just a matter of adding this record to the end of the record set, and ensuring that you have the correct opening and closing userRecords tag so that Alma will treat the file as a set of patron records.
If a record fails validation we normally just discard the record and write the student or staff number to output and print an error so that we can see there is a problem record. Most of the time the problem occurs when a non-standard character fails to convert to the equivalent XML ie &amp; appearing in the SIF record input, or the record is missing basic information like an address or expiry information.
The PHP include file also includes some functions to write a SIF record to a filehandle, since you may be receiving your data in SIF format, but need to supplement it with additional information ie barcodes that may not be provided by your record source, and so need a final SIF file to process.

The PHP include file from this blog are available here, but is for use at your own risk.