XSLT - XSLT <xsl:merge> for Combining Multiple Sorted XML Sources
Introduction
In XSLT 3.0, <xsl:merge> is used to combine information from multiple XML sources that are already sorted according to a common criterion. It is particularly useful when several XML documents contain related records and you want to process those records together based on a shared value.
For example, suppose a company stores employee information in one XML file and salary information in another XML file. Both files may contain an employee ID. Instead of processing the documents independently and trying to manually match the records, <xsl:merge> can combine the corresponding records according to the employee ID.
The important point is that <xsl:merge> is designed for merging multiple sorted sequences, rather than simply concatenating XML documents.
Why <xsl:merge> Is Needed
Consider two XML documents.
The first document contains employee information:
<employees>
<employee>
<id>101</id>
<name>John</name>
</employee>
<employee>
<id>102</id>
<name>Mary</name>
</employee>
<employee>
<id>103</id>
<name>David</name>
</employee>
</employees>
The second document contains salary information:
<salaries>
<employee>
<id>101</id>
<salary>50000</salary>
</employee>
<employee>
<id>102</id>
<salary>60000</salary>
</employee>
<employee>
<id>103</id>
<salary>55000</salary>
</employee>
</salaries>
Both documents are ordered by employee ID.
The desired result could be:
<employee-data>
<employee>
<id>101</id>
<name>John</name>
<salary>50000</salary>
</employee>
<employee>
<id>102</id>
<name>Mary</name>
<salary>60000</salary>
</employee>
<employee>
<id>103</id>
<name>David</name>
<salary>55000</salary>
</employee>
</employee-data>
This is a typical situation where <xsl:merge> becomes useful.
Basic Structure of <xsl:merge>
The general structure looks like this:
<xsl:merge>
<xsl:merge-source select="...">
<xsl:merge-key select="..."/>
</xsl:merge-source>
<xsl:merge-source select="...">
<xsl:merge-key select="..."/>
</xsl:merge-source>
<xsl:merge-action>
...
</xsl:merge-action>
</xsl:merge>
The main components are:
-
<xsl:merge>: The outer instruction that controls the merge operation. -
<xsl:merge-source>: Defines an input sequence that participates in the merge. -
<xsl:merge-key>: Specifies the value used to determine the ordering and matching of records. -
<xsl:merge-action>: Specifies what should happen when records from the different sources are encountered.
Understanding <xsl:merge-source>
Each <xsl:merge-source> identifies one source of data.
For example:
<xsl:merge-source select="doc('employees.xml')/employees/employee">
<xsl:merge-key select="id"/>
</xsl:merge-source>
Here:
select="doc('employees.xml')/employees/employee"
selects the employee records from the external XML document.
The merge key:
<xsl:merge-key select="id"/>
tells XSLT that the <id> element should be used as the sorting and merging criterion.
A second source could be defined as:
<xsl:merge-source select="doc('salaries.xml')/salaries/employee">
<xsl:merge-key select="id"/>
</xsl:merge-source>
Now both sources are being processed according to their employee ID.
Understanding <xsl:merge-key>
The merge key is one of the most important parts of the operation.
For example:
<xsl:merge-key select="id"/>
means that the value of the <id> element determines where each record belongs in the merged sequence.
If the records contain:
<id>101</id>
<id>102</id>
<id>103</id>
the merge operation processes them in that order.
The key does not have to be a simple element. It can also be an expression.
For example:
<xsl:merge-key select="@employee-id"/>
could be used when the identifier is stored in an attribute.
It can also be based on a more complex expression:
<xsl:merge-key select="upper-case(department)"/>
This allows the merge key to be calculated rather than simply copied from one XML node.
Understanding <xsl:merge-action>
<xsl:merge-action> determines what the transformation should do with the records being merged.
A simplified example is:
<xsl:merge-action>
<employee>
<xsl:value-of select="current-merge-key()"/>
</employee>
</xsl:merge-action>
The merge action is evaluated for each group of records having the same merge key.
This is an important distinction.
Suppose both XML documents contain employee ID 101. When the merge process reaches 101, the corresponding records from the different sources can be accessed together during the merge action.
current-merge-key()
XSLT provides the current-merge-key() function for use during merge processing.
For example:
<xsl:value-of select="current-merge-key()"/>
If the current group is associated with employee ID 102, this function returns:
102
This makes it possible to use the current merge key when constructing the output.
Accessing Records from Different Sources
One of the powerful features of <xsl:merge> is the ability to determine which input sources contributed records for the current merge key.
For example, you may have:
<xsl:merge-action>
<employee>
<id>
<xsl:value-of select="current-merge-key()"/>
</id>
<name>
<xsl:value-of select="?"/>
</name>
</employee>
</xsl:merge-action>
Within the merge action, XSLT provides merge-related context that allows the stylesheet to examine the records associated with the current key.
This is particularly useful when a record exists in one source but not another.
For example:
employees.xml
101
102
103
salaries.xml
101
103
When the merge reaches employee 102, there is an employee record but no corresponding salary record.
This makes <xsl:merge> useful for processing incomplete or partially overlapping datasets.
A More Practical Example
Suppose we have two XML files.
employees.xml:
<employees>
<employee>
<id>101</id>
<name>John</name>
</employee>
<employee>
<id>102</id>
<name>Mary</name>
</employee>
<employee>
<id>103</id>
<name>David</name>
</employee>
</employees>
salaries.xml:
<salaries>
<employee>
<id>101</id>
<salary>50000</salary>
</employee>
<employee>
<id>102</id>
<salary>60000</salary>
</employee>
<employee>
<id>103</id>
<salary>55000</salary>
</employee>
</salaries>
A simplified XSLT 3.0 stylesheet could be structured as:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<employee-data>
<xsl:merge>
<xsl:merge-source
select="doc('employees.xml')/employees/employee">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-source
select="doc('salaries.xml')/salaries/employee">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-action>
<employee>
<id>
<xsl:value-of select="current-merge-key()"/>
</id>
</employee>
</xsl:merge-action>
</xsl:merge>
</employee-data>
</xsl:template>
</xsl:stylesheet>
This example demonstrates the basic structure rather than attempting to show every possible merge feature.
Merge Processing Versus Simple Concatenation
It is important to understand that merging is not the same as simply combining two sequences.
Suppose we have:
Source A:
101
102
103
Source B:
101
102
103
Simple concatenation would produce:
101
102
103
101
102
103
The records remain separate.
A merge operation instead examines the ordering and merge keys:
101 -> Source A + Source B
102 -> Source A + Source B
103 -> Source A + Source B
This allows the stylesheet to process records belonging to the same key together.
Handling Records Present in Only One Source
A useful application is identifying missing information.
For example:
Employee source:
101
102
103
104
Salary source:
101
102
104
Employee 103 does not have a salary record.
A merge operation can detect this situation and produce output such as:
<employee>
<id>103</id>
<name>David</name>
<salary>Not Available</salary>
</employee>
This makes merging useful for data integration and reconciliation tasks.
Multiple XML Sources
<xsl:merge> is not restricted to two sources.
For example, an application might have:
employees.xml
salaries.xml
departments.xml
benefits.xml
All four sources could contain a common employee identifier.
Conceptually:
<xsl:merge>
<xsl:merge-source select="...">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-source select="...">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-source select="...">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-source select="...">
<xsl:merge-key select="id"/>
</xsl:merge-source>
<xsl:merge-action>
...
</xsl:merge-action>
</xsl:merge>
This allows information from multiple XML datasets to be processed according to a common ordering criterion.
Importance of Sorted Input
One of the key characteristics of <xsl:merge> is that each merge source is expected to be supplied in the order required by its merge key.
For example, if the merge key is:
<xsl:merge-key select="id"/>
the source should effectively be ordered as:
101
102
103
104
rather than:
103
101
104
102
The purpose of the merge mechanism is to efficiently combine sequences that are ordered according to their merge keys.
Therefore, understanding the ordering requirements is essential when designing a stylesheet using <xsl:merge>.
<xsl:merge> and Traditional Grouping
<xsl:merge> should not be confused with traditional grouping techniques.
Grouping is generally concerned with taking nodes from a sequence and organizing them into groups according to a grouping key.
For example, you might group employees by:
Department
and produce:
IT
John
Mary
HR
David
Susan
Merging has a different purpose. It is particularly useful when multiple independently supplied sequences need to be processed together according to a common ordering key.
For example:
Employee records Salary records
| |
+-------- ID --------+
|
Merge
|
Combined data
Thus, although both techniques use keys, they solve different data-processing problems.
Real-World Applications
<xsl:merge> can be useful in several practical situations.
Combining Customer Data
A company may maintain:
customers.xml
orders.xml
payments.xml
All three may contain a customer ID. Merge processing can help create a consolidated customer report.
Comparing Historical XML Data
Two XML files may represent data from different periods:
January.xml
February.xml
Records can be merged according to product ID, customer ID, or transaction ID.
Financial Data Processing
Financial systems may store transactions in separate XML files. Records can be processed according to account number or transaction date.
Log Processing
Multiple XML-based log files can be merged according to timestamp, allowing events from different systems to be processed chronologically.
Data Reconciliation
One source might contain a list of registered products while another contains inventory information. Merging can help identify products that exist in one source but are absent from another.
Advantages of <xsl:merge>
The major advantages include:
-
Multiple sources can be processed together.
-
Records can be associated through a common merge key.
-
It is well suited to sorted XML data.
-
It can handle sources that do not contain identical records.
-
It is useful for data integration and reconciliation.
-
It is part of the XSLT 3.0 feature set and is designed specifically for merge-style processing.
-
It can be more appropriate than manually comparing every record from every document.
Important Concepts to Remember
When learning <xsl:merge>, remember these four concepts:
Merge source:
Defines where the input records come from.
Merge key:
Defines the value according to which records are ordered and associated.
Merge action:
Defines what the transformation does with records encountered for a particular merge key.
Current merge key:current-merge-key() provides the key associated with the current merge group.
The overall process can be represented as:
XML Source 1 ──┐
│
XML Source 2 ──┼──> Merge Key ──> Merge Processing ──> Output
│
XML Source 3 ──┘
Conclusion
<xsl:merge> is an important XSLT 3.0 feature for integrating multiple ordered XML data sources. Instead of treating each XML document independently, it allows records from different sources to be processed together based on a common merge key.
Its greatest value appears when working with large or independently maintained XML datasets, such as employee records and salaries, customers and orders, inventory and product information, or multiple chronological XML feeds. By using <xsl:merge-source>, <xsl:merge-key>, and <xsl:merge-action>, an XSLT stylesheet can create sophisticated data-integration transformations while keeping the processing logic structured and maintainable.