Mashups in EMML : Writing Mashups in EMML : Transforming Intermediate Results : <group> : <group> Examples
<group> Examples
Define What to Group
You use an XPath expression in the by attribute to select a set of repeating nodes from a variable and identify the field whose unique values define each group, called the group key. You also set the outpuvariable attribute to hold the result.
<group by="$catalog//book/genre" outputvariable="$groupResult">
</group>
This example finds all unique genre values (the group key) for book nodes from the $catalog variable. Keep these points in mind:
*The XPath expression in the by attribute does not explicitly identify which nodes are the repeating items for the group, called the group items. Starting backwards from the final node in this XPath expression, the MashZone NextGen Server uses the first ancestor that repeats as the group items.
*The final node in this XPath is the group key and it must result in a simple value that can be compared. This can be an attribute or any child or descendant that contains simple data.
By default, this value is treated as a string. You can use functions in the XPath expression to cast key values to other types or to perform case conversions.
*Do not use predicates in the by attribute to filter which items should be selected. Instead, specify a filtering condition in the having attribute.
Copy and Sort to Construct the Result
You construct the grouped result to put into the output variable as literal XML with either literal data or Dynamic Mashup Expressions to generate data.
Important:  
The XPath expressions within literal XML for a <group> are relative to the repeating node in the by attribute.
Inside <group>, add the XML that should be generated as the result of the <group> statement for each group of repeating items. The XML must be well formed. So:
*Each group must be wrapped in a single node.
*You can also create the root node that wraps the entire document for the result.
Note:  
If you omit a document root node, the MashZone NextGen Server adds an <output> root node by default, using any namespace you have defined for the group items.
To include all data for each repeating item in the top-level group, use the {$group_id} dynamic mashup expression. See Nest Groups for examples of dynamic mashup expressions for subgroups.
This example sorts books in the $catalog variable by genre including full copies of each book with the genre group:
<group by="$catalog//book/genre" outputvariable="$groupResult">
<res:bookGenres>
<genre>{$group_id}</genre>
<res:bookGenres>
</group>
The result for this <group> statement would looks something like this:
<res:bookGenres>
<genre>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<keywords>XML software language nonfiction</keywords>
<price>44.95</price>
<copiessold>100</copiessold>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
<book id="bk110">
<author>O'Brien, Tim</author>
...
</book>
</genre>
<genre>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
...
</book>
....
</genre>
...
</res:bookGenres>
Include Unique Values in the Result
You can also pull out the unique values for the group key to include them in the result using the {$group_key} dynamic mashup expression. This example sorts books by genre in the $catalog variable, adding the name of each genre to the node wrapping the group:
<group by="$catalog//book/genre" outputvariable="$groupResult">
<res:bookGenres>
<genre name="{$group_key}">{$group_id}</genre>
<res:bookGenres>
</group>
The results would look something like this:
<res:bookGenres>
<genre name="Computer">
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<keywords>XML software language nonfiction</keywords>
<price>44.95</price>
<copiessold>100</copiessold>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
<book id="bk110">
<author>O'Brien, Tim</author>
...
</book>
</genre>
<genre name="Fantasy">
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
...
</book>
....
</genre>
...
</res:bookGenres>
Add Calculations to the Result
You can also perform calculations on the repeating items in each group using dynamic mashup expressions and XPath functions. Common examples include generating a count of items in the group or summing a numeric field for all items in the group. You can:
*Add these calculations to a group containing the sorted items.
You can use any XPath function that can perform calculations based on a set of nodes (a sequence). The path for this set of nodes must be a relative path to the repeating items for this group.
This example calculates the number of books in a given genre and adds this to the sorted output:
<group by="$catalog//book/genre" outputvariable="$groupResult">
<books>
<genre name="{$group_key}" count="{count(title)}">
{$group_id}</genre>
</books>
</group>
The count function accepts a set of nodes as input. In this case the relative path points to the title node in each book (the repeating item). The result for this <group> statement would look something like this:
<books>
<genre name="Computer" count="4">
<book id="bk101"> ... </book>
...
</genre>
<genre name="Fantasy" count="5">
<book id="bk102"> ... </book>
...
</genre>
...
</books>
*Or omit repeating item data and construct the result solely from group keys and calculations. This is useful if you only want statistics, not the actual data.
This example outputs just the name of book genres from the $catalog variable and calculates the total number of copies sold for that genre:
<group by="$catalog//book/genre" outputvariable="$groupResult">
<genre name="{$group_key}" copiessold="{sum(copiessold)}"/>
</group>
Note:  
As with all XPath expressions inside the constructed result for <group>, the dynamic mashup expression {sum(copiessold)} uses a path that is relative to the repeating item for <group>.
The result for the <group> statement would look something like this:
<output>
<genre name="Computer" sold="140"/>
<genre name="Fantasy" sold="1600"/>
<genre name="Horror" sold="1000"/>
<genre name="Romance" sold="700"/>
<genre name="Science Fiction" sold="400"/>
</output>
Filter With a Condition
You can optionally filter group items using a condition in the having attribute. This next example selects unique genres for all books whose prices are greater than 5:
<group by="$catalog//book/genre" having="price &gt; 5"
outputvariable="$groupResult">
...
</group>
The condition in having is an XPath expression that is relative to the group items defined in the by attribute. This filter affects both the repeating items included in the result and any calculations for the group.
Nest Groups
You can nest <group> elements within the literal XML of the result to get additional levels of grouping. The initial <group> statement defines the repeating items to be group. Nested <group> statements simply define additional levels of grouping.
The following example groups books in the $catalog variable by genre and author. It includes all book data:
<group outputvariable="$groupedResult" by="$catalog//book/genre">
<books>
<genre name="{$group_key}" copiessold="{sum(copiessold)}">
<group by="author">
<author name="{$group_key}" count="{count(title)}">
{$group_id1}
</author>
</group>
</genre>
</books>
</group>
The results would look something like this:
<res:bookGenres>
<genre name="Computer" copiessold="1567">
<author name="Gambardella, Mathew" count="1">
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<keywords>XML software language nonfiction</keywords>
<price>44.95</price>
<copiessold>100</copiessold>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
</author>
<author name="O'Brien, Tim" count="3">
<book id="bk110">
<author>O'Brien, Tim</author>
...
</book>
...
</author>
</genre>
<genre name="Fantasy">
....
</genre>
...
</res:bookGenres>
Some points to keep in mind for nested <group> statements:
*Nested group do not need an outputvariable attribute. The results of the nested group is included in the results of its parent group.
*Each level of grouping has its own group ID to include data for the repeating items for that group. The dynamic mashup expression is in the form {$group_idn} for subgroups. For the second level of grouping n = 1, for the third level n = 2 and so on.
Note:  
You can use {$group_idn}, {$group_idn-1} up to and including {$group_id} within a nested group to include repeating item data in the result.
If the path in the by attribute for a nested group does not contain a nested repeating item, then the repeating item for that group is the same as the parent group. Simply put, if you are grouping on another key for the same repeating items, then {$group_idn} outputs the exact same items as {$group_idn-1} or {$group_id} if the parent is the top level group.
If the path in the by attribute for a nested group does have a repeating item, this becomes the repeating item for that group. In this case, {$group_idn} outputs the nested level of repeating items while {$group_idn-1} outputs the parent level of repeating items and {$group_id} outputs the top level repeating items.
*The Xpath expression in the by attribute is relative to the repeating group items defined in the closest group level.
In the previous example, books were the group items for both levels. They were grouped first by genre, then author within genre.
You can also have several levels of group items. For example:
<group outputvariable="$groupedResult"
by="$inventory//items/item/sku">
<res:items>
<res:item id="{$group_key}" quantity="{sum(quantity)}" ...>
<group by="parts/part/partno">
<res:parts>
<res:part partno="{$group_key}"
quantity="{sum(quantity)}".../>
</res:parts>
</group>
</res:item>
</res:items>
</group>
The first group in this example is for items and the XPath to calculate the quantity in inventory is based on item/quantity.
The second group, however, also has repeating nodes in the by attribute - item/parts/part nodes. This becomes the group items for the second group and the quantity calculation is based on part/quantity.
*The variable $group_key is relative to the scope of the group that it is used in. So in the first example, the first $group_key generates book genres and the second generates authors.
*Calculations or the results of any XPath functions are based on the group level they are used in.
Working Samples
The following sample mashups use the <group> statement:
*GroupByService (groupby.emml) for the basics
*GroupByService (employeegroups.emml) an example of nested groups including all repeating items data
*GroupStocks (groupstocks.emml) an examle of including all repeating items data
See Mashup Samples for a list of MashZone NextGen mashup samples and where to find them.
Copyright © 2013-2016 Software AG, Darmstadt, Germany.

Product LogoContact Support   |   Community   |   Feedback