This article will show us how to merge XDocument Files
Introduction
Let us say that we have two XML structures as under
XML Structure1
<scriptfilenames>
<SqlEye>
<scriptfilename Name="ws_CallLogs_GetByCallId.sql" Type="SP">
<SqlEyeWarnings>
<SqlEyeWarning value="SD030: object does not exist in database or is invalid for this operation in Database : ws_CallLogs @ line number : 63" />
</SqlEyeWarnings>
<FxCopsWarnings>
<FxCopsWarning value="Avoid using sp_ as a prefix for stored procedure " />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value="SP017: Consider using EXISTS predicate instead of IN predicate @ line number : 1" />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value="Missing or order mismatch of Grant statement." />
</FxCopsRemarks>
</scriptfilename>
</SqlEye>
</scriptfilenames>
XML Structure2
<scriptfilenames>
<SqlEye>
<scriptfilename Name="dbo.StopAutoRenewalEx.StoredProcedure.sql" Type="SP">
<SqlEyeWarnings />
<FxCopsWarnings>
<FxCopsWarning value="Missing schema while addressing object name" />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value="SP016: Update statements should not update primary key @ line number : 70" />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value="Values hardcoded in where-clause condition " />
</FxCopsRemarks>
</scriptfilename>
</SqlEye>
</scriptfilenames>
Now after merge, the result should be
<scriptfilenames>
<SqlEye>
<scriptfilename Name="ws_CallLogs_GetByCallId.sql" Type="SP">
<SqlEyeWarnings>
<SqlEyeWarning value="SD030: object does not exist in database or is invalid for this operation in Database : ws_CallLogs @ line number : 63" />
</SqlEyeWarnings>
<FxCopsWarnings>
<FxCopsWarning value="Avoid using sp_ as a prefix for stored procedure " />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value="SP017: Consider using EXISTS predicate instead of IN predicate @ line number : 1" />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value="Missing or order mismatch of Grant statement." />
</FxCopsRemarks>
</scriptfilename>
<scriptfilename Name="dbo.StopAutoRenewalEx.StoredProcedure.sql" Type="SP">
<SqlEyeWarnings />
<FxCopsWarnings>
<FxCopsWarning value="Missing schema while addressing object name" />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value="SP016: Update statements should not update primary key @ line number : 70" />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value="Values hardcoded in where-clause condition " />
</FxCopsRemarks>
</scriptfilename>
</SqlEye>
</scriptfilenames>
This article will show two solutions to do the same.
Environment Setup
Let us first write the below code snippet for making the XML documents
private static XDocument FirstXMLStructure()
{
var xmlContent = @"<scriptfilenames>
<SqlEye>
<scriptfilename Name='ws_CallLogs_GetByCallId.sql' Type='SP'>
<SqlEyeWarnings>
<SqlEyeWarning value='SD030: object does not exist in database or is invalid for this operation in Database : ws_CallLogs @ line number : 63' />
</SqlEyeWarnings>
<FxCopsWarnings>
<FxCopsWarning value='Avoid using sp_ as a prefix for stored procedure ' />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value='SP017: Consider using EXISTS predicate instead of IN predicate @ line number : 1' />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value='Missing or order mismatch of Grant statement.' />
</FxCopsRemarks>
</scriptfilename>
</SqlEye>
</scriptfilenames>";
return XDocument.Parse(xmlContent);
}
private static XDocument SecondXMLStructure()
{
var xmlContent =@"<scriptfilenames>
<SqlEye>
<scriptfilename Name='dbo.StopAutoRenewalEx.StoredProcedure.sql' Type='SP'>
<SqlEyeWarnings />
<FxCopsWarnings>
<FxCopsWarning value='Missing schema while addressing object name' />
</FxCopsWarnings>
<SqlEyeRemarks>
<SqlEyeRemark value='SP016: Update statements should not update primary key @ line number : 70' />
</SqlEyeRemarks>
<FxCopsRemarks>
<FxCopsRemark value='Values hardcoded in where-clause condition ' />
</FxCopsRemarks>
</scriptfilename>
</SqlEye>
</scriptfilenames>";
return XDocument.Parse(xmlContent);
}
Now use the below program to load the documents
static void Main(string[] args)
{
var xmls = new List<XDocument>
{ FirstXMLStructure(),
SecondXMLStructure()
};
}
Solution1
Use LINQ to XML to select the list of <scriptfilename>" elements and add them to a new XDocument
var resultXml1 = new XDocument
(
new XElement("scriptfilenames",
new XElement("SqlEye",xmls.Descendants("scriptfilename")))
);
Solution2
Extract the portion <scriptfilename>" and wrap it up using Stringbuilder for the Root Nodes.
StringBuilder sb = new StringBuilder();
sb.AppendLine("<scriptfilenames><SqlEye>");
int cnt = xmls.Count;
for (int i = 0; i < cnt; i++)
{
var value = xmls[i];
var findContent = value.Descendants("scriptfilename");
sb.AppendLine(value.Descendants("scriptfilename").ToList()[0].ToString());
}
sb.AppendLine("</SqlEye></scriptfilenames>");
var resultXml2 = sb.ToString();
Among these two, I would prefer the first one as it is much more neat and clean and no extra string operation is needed.
Conclusion
So in this article we have learnt as how to join / merge two or more XDocument structures / files.Thanks for reading.Zipped file is attached.