In some instances, we may have the need to extend the
information in a XML payload by merging multiple documents into one. When using
the System.Xml.Linq.XDocument class, there is no method to allow us to do a
merge. On this article, we extend the XDocument class to provide the Merge
capabilities.
XML
Documents:
We first start by showing two XML documents that can be
combined into one. The base requirement with this approach is that both
documents are similar with the exception of one Element that contains some
unique information that is not contained on the other XML.
XML with Annual Data
|
XML with YTD Data
|
Merged XML
|
<Finance>
<Company>
<Name>OG-BIT</Name>
</Company>
<Annual>
<col1>100</col1>
<col2 />
</Annual>
</Finance>
|
<Finance>
<Company>
<Name>OG-BIT</Name>
</Company>
<YTD>
<col1>100</col1>
<col2>200</col2>
</YTD>
</Finance>
|
<Finance>
<Company>
<Name>OG-BIT</Name>
</Company>
<YTD>
<col1>100</col1>
<col2>200</col2>
</YTD>
<Annual>
<col1>100</col1>
<col2 />
</Annual>
</Finance>
|
The company and annual information needs to be maintained.
|
From this XML, we need to extract the YTD information
|
The outcome should be a document with both reports and with single
company information.
|
Extension Methods:
An approach to provide this feature is to create extension
methods that implement the merge. This is done by adding the following static
class:
/// <summary>
/// extension methods to enable the merge of xml documents
/// </summary>
internal static class XDocumentExtension
{
/// <summary>
/// merge an element from one document to the root of another
/// </summary>
/// <param
name="refDoc"></param>
/// <param
name="doc"></param>
/// <param
name="elementName"></param>
internal static void Merge(this XDocument refDoc, XDocument doc, string elementName)
{
if (doc != null && !String.IsNullOrWhiteSpace(elementName))
{
//find
the element by name
var segment = doc.Descendants().Where(elm =>
elm.Name.LocalName= elementName).Select(elm => elm).FirstOrDefault();
//if
found add to the original document at the root
if (segment != null)
refDoc.Root.Add(segment);
}
}
/// <summary>
/// merge an xml string into a XDocument reference
/// </summary>
/// <param
name="refDoc"></param>
/// <param
name="xml"></param>
/// <param
name="elementName"></param>
internal static void Merge(this XDocument refDoc, string xml, string elementName)
{
if (!String.IsNullOrWhiteSpace(xml) && !String.IsNullOrWhiteSpace(elementName))
{
XDocument doc = XDocument.Parse(xml);
refDoc.Merge(doc, elementName);
}
}
/// <summary>
/// returns the xml string with header declaration
/// </summary>
/// <param
name="doc"></param>
/// <returns></returns>
internal static string ToStringWithDeclaration(this XDocument doc)
{
return String.Format("{0}{1}", doc.Declaration, doc.ToString());
}
}
This is the description for this class:
Method
|
Description
|
Merge (XDocument, string)
|
Merges two XDocument references by finding an element with the LocalName
equal to the parameter value.
|
Merge (string, string)
|
Loads the XML string into an XDocument reference and calls the Merge
method.
|
ToStringWithDeclaration
|
Gets the merged XML string with the Declaration header when found (i.e.
<?xml>)
|
Example:
The following example uses the extension methods to merge
the documents and returns the merged XML string:
public static void main()
{
string xml1 = @"<Finance><Company><Name>OG-BIT</Name></Company><YTD><col1>100</col1><col2>200</col2></YTD></Finance>";
string xml2 = @"<Finance><Company><Name>OG-BIT</Name></Company><Annual><col1>100</col1><col2/></Annual></Finance>";
XDocument doc = XDocument.Parse(xml1);
doc.Merge(xml2, "Annual");
string xml =
doc.ToStringWithDeclaration();
}
This simple example illustrates an approach of how this can
be done when using the XDocument class. There are other ways of achieving the
same with other classes.
Thanks for
reading.
0 comments :
Post a Comment
What do you think?