Document Transform Activities

Document Transform activities can be used when you need to draw from elements from a process variable whose type is document to populate elements on another document variable. The transformation rules are specified declaratively as an attribute of your transform activity. Two distinct syntaxes are supported: Groovy GPath and XSLT. Configuration of the transform activity is the same whichever syntax you decide to use; only the language constructs in your transform specification are different.

To illustrate the workings of a Document Transform activity, assume that you have an input variable named vacationPlan whose type is XmlBean. Let's say the document content looks like this:
<VacationPlan xmlns="http://mdw.centurylink.com/XMLSchema">
  <Request id="12345678" />
  <Traveler cuid="dxoakes">
    <Name>Donald Oakes</Name>
    <Department>IT</Department>
    <Supervisor cuid="tfujimu">
      <Name>Tai Fujimura</Name>
    </Supervisor>
  </Traveler>
  <Departure>15-Dec-2008</Departure>
  <Return>31-Dec-2008</Return>
  <VacationPackage>Ski Trip</VacationPackage>
  <TravelPrefs>
    <Smoking>No</Smoking>
    <Vegetarian>Yes</Vegetarian>
  </TravelPrefs>
  <Hotel id="1234567">
    <Name>The Lodge at Breckenridge</Name>
    <Address>112 Overlook Drive, Breckenridge, Colorado 80424</Address>
  </Hotel>
</VacationPlan>

You would like to transform the vacationPlan document into a ManagerApprovalRequest which will be sent via some interface downstream in your process. In the MDW Studio configurator for your activity, you select your vacationPlanner variable as the input document. For a GPath transform with an output document variable called gpathOutput, your transform declaration would be as follows:
def managerName = vacationPlan.Traveler.Supervisor.Name =~ /(.*)\s(.*)/
def requesterName = vacationPlan.Traveler.Name =~ /(.*)\s(.*)/

gpathOutput.ManagerApprovalRequest(xmlns:'http://mdw.centurylink.com/XMLSchema', 'xmlns:bim':'http://www.centurylink.com/XMLSchema/BIM') {
  Request(id:'12345') {
    Date(new Date().format('MM/dd/yyyy'))
  }
  Approver() {
    'bim:CUID'(vacationPlan.Traveler.Supervisor.'@cuid')
    'bim:FirstName'(managerName[0][1])
    'bim:LastName'(managerName[0][2])
  }
  Requester() {
    'bim:CUID'(vacationPlan.Traveler.'@cuid')
    'bim:FirstName'(requesterName[0][1])
    'bim:LastName'(requesterName[0][2])
  }
  TimeOff(local:vacationPlan.FlightPlan == '') {
    StartDate(Date.parse('dd-MMM-yyyy', vacationPlan.Departure.text()).format('MM/dd/yyyy'))
    EndDate(Date.parse('dd-MMM-yyyy', vacationPlan.Return.text()).format('MM/dd/yyyy'))
  }
}

This syntax builds a new document from scratch based on the appropriate values from the input document. In your process downstream of the transform activity the gpathOutput variable would be available as follows:
<ManagerApprovalRequest xmlns="http://mdw.centurylink.com/XMLSchema" xmlns:bim="http://www.centurylink.com/XMLSchema/BIM">
  <Request id="12345">
    <Date>01/20/2009</Date>
  </Request>
  <Approver>
    <bim:CUID>tfujimu</bim:CUID>
    <bim:FirstName>Tai</bim:FirstName>
    <bim:LastName>Fujimura</bim:LastName>
  </Approver>
  <Requester>
    <bim:CUID>dxoakes</bim:CUID>
    <bim:FirstName>Donald</bim:FirstName>
    <bim:LastName>Oakes</bim:LastName>
  </Requester>
  <TimeOff local="true">
    <StartDate>12/15/2008</StartDate>
    <EndDate>12/31/2008</EndDate>
  </TimeOff>
</ManagerApprovalRequest>

To perform a similar transformation using XSLT syntax, you would specify the following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://mdw.centurylink.com/XMLSchema" xmlns:bim="http://www.centurylink.com/XMLSchema/BIM" xmlns:q="http://mdw.centurylink.com/XMLSchema">

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="q:VacationPlan">
  <ManagerApprovalRequest>
    <xsl:apply-templates select="q:Request | q:Traveler"/>
  </ManagerApprovalRequest>
</xsl:template>

<xsl:template match="q:Request">
  <Request><xsl:attribute name="id"><xsl:value-of select="./@id"/></xsl:attribute>
    <Date>12/15/2008</Date>
  </Request>
</xsl:template>

<xsl:template match="q:Traveler">
  <xsl:variable name="managerName" select="q:Supervisor/q:Name"/>
  <Approver>
    <bim:CUID><xsl:value-of select="./q:Supervisor/@cuid"/></bim:CUID>
    <bim:FirstName><xsl:value-of select="substring-before($managerName, ' ')"/></bim:FirstName>
  </Approver>
</xsl:template>

</xsl:stylesheet>

You can also use GPath syntax to manipulate a pre-existing document variable rather than building one from scratch. Say you had a document variable called gpathInputOutput whose contents looked like this:
<GPathInputOutputDoc>
  <Request id="54321">
    <Date>01/20/2009</Date>
  </Request>
  <ToBeFilledInElement id="12345"/>
  <ElementWithMissingAttribute/>
  <ElementWithSomeChildren>
    <ChildOne>ChildOneValue</ChildOne>
    <ChildTwo/>
  </ElementWithSomeChildren>
</GPathInputOutputDoc>

You could configure your GPath transform as follows:
def tbf = gpathInputOutput.findAll{ it.@id == '12345' }
tbf.each { t ->
    t.value = vacationPlan.Traveler.@cuid
}
gpathInputOutput.ElementWithMissingAttribute.@newAttr = 'newAttrValue'
gpathInputOutput.ElementWithSomeChildren.ChildTwo[0].value = 'ChildTwoValue'
gpathInputOutput.ElementWithSomeChildren[0].appendNode('ChildThree', 'ChildThreeValue')

In this case after the transform activity executes, your document would look like this:
<GPathInputOutputDoc>
  <Request id="54321">
    <Date>01/20/2009</Date>
  </Request>
  <ToBeFilledInElement id="12345">dxoakes</ToBeFilledInElement>
  <ElementWithMissingAttribute newAttr="newAttrValue"/>
  <ElementWithSomeChildren>
    <ChildOne>ChildOneValue</ChildOne>
    <ChildTwo>ChildTwoValue</ChildTwo>
    <ChildThree>ChildThreeValue</ChildThree>
  </ElementWithSomeChildren>
</GPathInputOutputDoc>