Fun with HealthVault transforms

It is sometimes useful to be able to display data in an application without having to understand the details of that data.

To make this easier, HealthVault provides a couple of features: transforms, and the HealthRecordItemDataGrid class.

Discovering transforms

To find out what transforms are defined for a specific type, we just ask the platform:

    HealthRecordItemTypeDefinition definition =
             ItemTypeManager.GetHealthRecordItemTypeDefinition(Height.TypeId, ApplicationConnection);

In this case, we get back the definition of the Height thing type. In the returned HealthRecordItemTypeDefinition (which I’ll just call “type definition” for simplicity), you can find the schema for the type (in the XmlSchemaDefinition property), and two properties related to transforms.

SupportedTransformNames lists the names of the transforms. In this case, the list is “form”, “mtt”, and “stt” (more on what these do later).

TransformSource contains the XSL transforms themselves, keyed with the name of the transform.

Applying transforms

If you want to apply the transform, there are two ways to do it.

The first way is to do it on the client side:

    string transformedXml = definition.TransformItem(“mtt”, heightInstance);

That’s pretty straightforward, though you do need to fetch the type definition for the type first. You could also apply the transform using the .NET XML classes, if you wanted to do more work.

The second option is to ask the platform to do the transform for you. You do this by specifying the transform name as part of the filter definition:

    HealthRecordFilter filter = new HealthRecordFilter(Height.TypeId);
    filter.View = new HealthRecordView();
    filter.View.TransformsToApply.Add("mtt");
    filter.View.Sections = HealthRecordItemSections.Core;

and then the item will already have the transformed text inside of it:

    XmlDocument mttDocument = heightInstance.TransformedXmlData["mtt"];

Available transforms

Each type defines a set of transforms that let you look at a data instance in a more general way. The are named “mtt”, “stt”, and “form”.

“mtt” transform

The mtt (which stands for “multi type transform”) generates the most condensed view of data – it returns values for properties that are present on all data types, and a single summary string.

For example, asking for the mtt transform of a Height instance returns the following:

<row wc-id="8608696a-94b3-41a8-b9a6-219ecbbc87d1" 
     wc-version="1e715849-43d7-4a72-9c65-8163649c0f84" 
     wc-note="" 
     wc-tags="" 
     wc-date="2008-01-22 11:12:42" 
     wc-type="Height Measurement" 
     wc-typeid="40750a6a-89b2-455c-bd8d-b420a4cb500b" 
     wc-source="" 
     wc-brands="" 
     wc-issigned="False" 
     wc-flags="" 
     wc-ispersonal="false" 
     wc-relatedthings="" 
     summary="1.9405521428867 m" />

The “wc-“ attributes are the common data items across all instances. The most interesting piece of data is the summary attribute, which gives you the (surprise!) summary string for the instance.

“stt” transform

The stt (“single type transform”) is similar to the mtt, but instead of a single summary attribute there are a series of attributes that correspond to the properties on the data type. It will generally contain a attribute for every important property, but if the property is a less important detail and/or the type is very complex, this may not be true.

For our Height instance, we get this for the mtt transform

<row
  wc-id="8608696a-94b3-41a8-b9a6-219ecbbc87d1"
  wc-version="1e715849-43d7-4a72-9c65-8163649c0f84"
  wc-note=""
  wc-tags=""
  wc-date="2008-01-22 11:12:42"
  wc-type="Height Measurement"
  wc-typeid="40750a6a-89b2-455c-bd8d-b420a4cb500b"
  wc-source=""
  wc-brands=""
  wc-issigned="False"
  wc-flags=""
  wc-ispersonal="false"
  wc-relatedthings=""
  when="2008-01-22 11:12:42"
  display="1.9405521428867 m"
  height-in-m="1.9405521428867" />

How do we know what attributes are here and what to do with them?

That information is stored in the ColumnDefinitions property of the type definition. Each of these (an ItemTypeDataColumn instance) corresponds to one of the attributes on the row created by the STT transform.

The following code can be used to pull out the values:

    XmlNode rowNode = item.TransformedXmlData["stt"].SelectSingleNode("data-xml/row");

    foreach (ItemTypeDataColumn columnDefinition in definition.ColumnDefinitions)
    {
        XmlAttribute columnValue = rowNode.Attributes[columnDefinition.ColumnName];
    }

This is the mechanism that the HealthVault shell uses to display detailed information about an instance. There is additional information in the ItemTypeDataColumn that it uses:

The Caption property stores a textual name for the column.

The ColumnTypeName property stores the type of the column.

The ColumnWidth contains a suggested width to use to display this information.

The VisibleByDefault property defines whether the column is visible in the shell view by default (the wc-<x> ones typically are not, with the exception of wc-date).

HealthRecordItemDataGrid

If you don’t want to decode all the column information yourself, you can use the HealthRecordItemDataGrid in your project.

Put the following after the page directive in your .aspx file:

    <%@ Register TagPrefix="HV" Namespace="Microsoft.Health.Web"  Assembly="Microsoft.Health.Web" %>

and then put an instance of the grid in the appropriate place:

    <HV:HealthRecordItemDataGrid ID="c_itemDataGrid" runat="server" />

You then create a filter that defines the data to show in the grid in the page load handler:

    c_itemDataGrid.FilterOverride = new HealthRecordFilter();
    c_itemDataGrid.FilterOverride.TypeIds.Add(AerobicSession.TypeId);

and the grid will be rendered using the STT transform view. If you want it to use the MTT transform view, you can set the TableView property on the grid to MultipleTypeTable, and it will show a summary view. You will also see this view if the filter returns more than one thing type.

The form transform

The final transform is the form transform. This transform exists on most, though not all types (we’re working to add form transforms where they’re absent). It provides an HTML view of the type.

For our Height instance, we get the following from the form transform:

<div class="xslThingTitle" id="genThingTitle">Height</div>
<div class="xslThingValue">1.9405521428867 m</div>
<table class="xslThingTable">
  <tr>
    <td class="xslTitleColumn">Date</td>
    <td class="xslValueColumn">2008-01-22 11:12:42</td>
  </tr>
</table>

which, when rendered, looks something like this:

Height

1.9405521428867 m

Date 2008-01-22 11:12:42

Other transforms

Some thing types will return a list that contain other transforms with names like “wpd-F5E5C661-26F5-46C7-9C6C-7C4E99797E53” or “hvcc-display”. These transforms are used by HealthVault Connection Center, for things like transforming WPD data into the proper xml format for a HealthVault instance.