Mapping XML elements with multiple (0...n) cardinality

When you need to map a source element to a target element with multiple cardinality (0...n) in the XML mapping editor, you can use the simple Create Mapping function for a simple mapping, or the XSL choose capability for a more complex mapping. This section uses examples to show you how to use both functions.

The cardinality of an element defines the number of possible occurrences of the element. The attributes that describe the cardinality of an element are minOccurs (minimum number of elements) and maxOccurs (maximum number of occurrences). If the maxOccurs attribute of an element has a value of greater than 1 or unbounded, that element has multiple cardinality. Here are some examples of cardinality:
minOccurs="0", or [0..*]
the element is optional, and there can be any number of occurrences
minOccurs="1" maxOccurs "1"
there must be one and only one occurrence
minOccurs="0" maxOccurs="2", or [0..2]
the element is optional, and there can be up to 2 occurrences
minOccurs="1" maxOccurs="5", or [1..5]
there must be at least 1 occurrence and no more than 5 occurrences
maxOccurs="5", or [1..5]
there must be at least 1 occurrence and no more than 5 occurrences

Consider this example: a complex type customerOrder may contain a deliveryDates element with attribute "maxOccurs=2". This means that the customerOrder can have a list of at most two delivery dates.

In the XML schema, the deliveryDates element will look like this:
<xsd:element maxOccurs="2" minOccurs="0" name="deliveryDates" type="xsd:dateTime"/>

In the XML mapping editor, the deliveryDates element looks like this:
Element with multiple cardinality in the XML mapping editor

If you are mapping from a source element with multiple cardinality to a target element with multiple cardinality, you may be able to use a simple Create Mapping function in certain cases. For example, if the maxOccurs of the target element is large enough to contain the source elements. In the following image in the XML Mapping editor, the mapping between the source items element and the target items element is achieved using the Create Mapping function.
Mapping of multiple cardinality element using Create mapping function

If you want to map a source element to a specific instance of a target element with multiple cardinality, a simple Create Mapping function is not sufficient, and you need to use XSL choose. In the remainder of this topic, we use an example to illustrate how to use XSL Choose to map multiple cardinality elements.

In this example, we have a sourceOperation that contains an order element, and a targetOperation that contains a customerOrder element. This is how they look in the XML mapping editor:
source and target elements in the XML mapping editor
These are the elements that we want to map:
Table 1. Elements to be mapped
Source Source type Target Target type
id int id int
billingAddress[1].addressLine1 string billingAddr [1] string
billingAddress[1]addressLine2 string billingAddr [2] string
ItemID [x] int items[x] -> ID int
ItemQuantities [x] int items[x] -> quantity int
availableDeliveryDates [1] dateTime deliveryDates [1] dateTime
availableDeliveryDates [2] dateTime deliveryDates [2] dateTime
shippingAddress1 string shipToAddress [1] string
shippingAddress2 string shipToAddress [2] string
salesReps[1] int reps[1] int
supportReps[1] int reps[2] int
Map the elements using the procedure described below. For step by step instructions on defining XSL choose, see Adding <xsl:choose>instructions to your mapping:
  1. When mapping specific elements in a list, first create a mapping between the parent elements of the source and the target. Choose a parent that does not have cardinality. A mapping created on the child elements will only map the first elements in the list. Begin by creating a mapping between the parent elements order and customerOrder.
  2. The id element is a simple type, and so it can be mapped directly. Use the Create mapping menu item to map the id element of the source to the id element of the target.
  3. Add an XSL Choose instruction on the customerOrder element, with the following content
    <xsl:choose>
       1 <xsl:when test="true()"> 
       2  <xsl:if test="/body/sourceOperation/order/shippingAddress1/text()">
    	 3 <shipToAddress>
    		<xsl:value-of select="/body/sourceOperation/order/shippingAddress1/text()"/>
    	</shipToAddress>
    </xsl:if>
     4 <xsl:if test="/body/sourceOperation/order/shippingAddress2/text()">
    	<shipToAddress>
    		<xsl:value-of select="/body/sourceOperation/order/shippingAddress2/text()"/>
    	</shipToAddress>
    </xsl:if>
     5 <xsl:if test="/body/sourceOperation/order/availableDeliveryDates[1]/text()">
     6 	<deliveryDates>
    		<xsl:value-of select="/body/sourceOperation/order/availableDeliveryDates[1]/text()"/>
    	</deliveryDates>
    </xsl:if>
    <xsl:if test="/body/sourceOperation/order/availableDeliveryDates[2]/text()">
    	<deliveryDates>
    		<xsl:value-of select="/body/sourceOperation/order/availableDeliveryDates[2]/text()"/>
    	</deliveryDates>
    </xsl:if>
     7 	<xsl:if test="/body/sourceOperation/order/billingAddress[1]/addressLine1/text()">
    	<billingAddr>
    		 8 <xsl:value-of select="/body/sourceOperation/order/billingAddress[1]/addressLine1/text()"/>
    	</billingAddr>
    </xsl:if>
    <xsl:if test="/body/sourceOperation/order/billingAddress[1]/addressLine2/text()">
    	<billingAddr>
    		<xsl:value-of select="/body/sourceOperation/order/billingAddress[1]/addressLine2/text()"/>
    	</billingAddr>
    </xsl:if>
    <xsl:if test="/body/sourceOperation/order/salesReps[1]/text()">
    	<reps>
    		<xsl:value-of select="/body/sourceOperation/order/salesReps[1]/text()"/>
    	</reps>
    </xsl:if>
    <xsl:if test="/body/sourceOperation/order/supportReps[1]/text()">
    	<reps>
    		<xsl:value-of select="/body/sourceOperation/order/supportReps[1]/text()"/>
    	</reps>
    </xsl:if>
      </xsl:when>
    </xsl:choose>
    Let's examine the parts of the XSL choose element:
    •  1  Invokes the XSL choose all the time (condition is always true).
    •  2  Checks whether text exists in the shippingAddress1 element in the source order.
    •  3  Creates a shipToAddress tag in the target customerOrder, and sets the value of the shipToAddress tag to the value of the shippingAddress1 element from the source order.
    •  4  Same as  2 , except the shippingAddress2 element from the source order is evaluated, and used as the value for the new shipToAddress tag.
    •  5  Checks whether the first availableDeliveryDates element exists in the source order.
    •  6  Creates a deliveryDates tag in the target customerOrder, and sets the value of the deliveryDates tag to the value of the first availableDeliveryDates element in the source order.
    •  7  Checks whether the addressLine1 element exists in the first billingAddress element of the source order.
    •  8  Sets the value of the new billingAddr tag in the target customerOrder to be the value of the addressLine1 element in the first billingAddress element of the source order.
  4. Add an XSL Choose on the target items element, with this content:
     1 <xsl:for-each select="/body/sourceOperation/order/itemID">
     2 	<xsl:variable name="itemIndex"><xsl:number/></xsl:variable>
    	 3 	<ID>
    			<xsl:value-of select="text()"/>
    		</ID>
    		 4 <quantity>
    			<xsl:value-of select="/body/sourceOperation/order/itemQuanities[position()=$itemIndex]"/>
    		</quantity>
    </xsl:for-each>
    Let's examine the XSL choose:
    •  1  Loops over each itemID element in the source order.
    •  2  Stores the index of the current itemID .
    •  3  Creates an ID tag for the target customerOrder and sets the value of the ID tag to the value of the current item element.
    •  4  Creates a quantity tag for the target customerOrder, and sets the value of the quantity tag to the value of the itemQuanties element at the current index.
Let's suppose that this was your input to the XSL transform:
  
	...
	<sourceOperation>
    <order>
      <id>049728</id>
      <billingAddress>
        <addressLine1>221B Baker Street</addressLine1>
        <addressLine2>London, UK</addressLine2>
      </billingAddress>
      <itemID>CAP001</itemID>
      <itemID>PIPE002</itemID>
      <itemQuanities>1</itemQuanities>
      <itemQuanities>2</itemQuanities>
      <availableDeliveryDates>2001-12-31T12:00:00</availableDeliveryDates>
      <availableDeliveryDates>2002-12-31T12:00:00</availableDeliveryDates>
      <shippingAddress1>63, Aston Road North</shippingAddress1>
      <shippingAddress2>Birmingham</shippingAddress2>
      <shippingAddress2>UK</shippingAddress2>
      <salesReps>1</salesReps>
      <salesReps>2</salesReps>
      <supportReps>3</supportReps>
      <supportReps>4</supportReps>
      <type>1</type>
    </order>
  </sourceOperation>
 ...
Given the above input, this would be the output xml:
...
  <targetOperation>
    <customerOrder>
      <shipToAddress>63, Aston Road North</shipToAddress>
      <shipToAddress>Birmingham</shipToAddress>
      <deliveryDates>2001-12-31T12:00:00</deliveryDates>
      <deliveryDates>2002-12-31T12:00:00</deliveryDates>
      <billingAddr>221B Baker Street</billingAddr>
      <billingAddr>London, UK</billingAddr>
      <reps>1</reps>
      <reps>3</reps>
      <id>049728</id>
      <items>
        <ID>CAP001</ID>
        <quantity>1</quantity>
        <ID>PIPE002</ID>
        <quantity>2</quantity>
      </items>
    </customerOrder>
  </targetOperation>
	...     
In this topic we have covered some examples of XSL choose. For more information on XSL choose syntax, see the XSLT specification at http://www.w3.org/TR/xslt .

Feedback
(C) Copyright IBM Corporation 2005, 2006. All Rights Reserved.