in src/FabActUtil/Generator/XmlSerializationUtility.cs [96:185]
private static string InsertXmlComments(string contentWithComments, string contentWithoutComments)
{
var commentNodes = XDocument.Parse(contentWithComments).DescendantNodes().OfType<XComment>();
var xdoc = XDocument.Parse(contentWithoutComments);
// if there are no comments to insert, just return the contentsWithoutComments
if (!commentNodes.Any())
{
return contentWithoutComments;
}
foreach (var commentNode in commentNodes)
{
var newComment = new XComment(commentNode.Value);
// Handle comments at beginning and end of xml
if (commentNode.Parent == null)
{
// Handle comments at beginning of xml
if (commentNode.PreviousNode == null && commentNode.NextNode != null)
{
xdoc.Root.AddBeforeSelf(newComment);
}
// Handle comments at end of xml
if (commentNode.NextNode == null && commentNode.PreviousNode != null)
{
xdoc.Root.AddAfterSelf(newComment);
}
}
else
{
// If Parent node of comment is not found in new xml, then dont add this comment.
var parent = xdoc.Descendants(commentNode.Parent.Name).FirstOrDefault();
if (parent != null)
{
var hadPrevious = commentNode.ElementsBeforeSelf().Any();
var hadNext = commentNode.ElementsAfterSelf().Any();
if (!hadNext)
{
// Handles if comment is last child of parent.
// Also handles if comment had no siblings i.e. node only has this comment.
parent.Add(newComment);
}
else if (!hadPrevious)
{
// Handles if comment is first child of parent.
parent.AddFirst(newComment);
}
else if (hadPrevious && hadNext)
{
// Handles if comment had both Previous and Next siblings.
// If PreviousNode of comment is in new Xml, add newComment after PreviousNode
// If PreviousNode is not in new xml and NextNode is in newXml, add newComment before NextNode.
// If both PreviousNode and NextNode is not in new xml skip it.
var previousInOriginal = commentNode.ElementsBeforeSelf().Last();
var nextInOriginal = commentNode.ElementsAfterSelf().First();
// Find matching Previous and Next siblings in new xml. Siblings must match in attributes as well.
var previous = FindNodeInXDocument(xdoc, previousInOriginal);
var next = FindNodeInXDocument(xdoc, nextInOriginal);
if (previous != null)
{
previous.AddAfterSelf(newComment);
}
else if (next != null)
{
next.AddBeforeSelf(newComment);
}
}
}
}
}
// Use XmlWriterSettings same as used in serialization to keep changes to existing files to minimal.
var stringBuilder = new StringBuilder();
using (var memoryStream = new MemoryStream())
{
using (var xmlWriter = XmlWriter.Create(memoryStream, XmlSerializationUtility.GetXmlWriterSettings()))
{
xdoc.Save(xmlWriter);
xmlWriter.Flush();
memoryStream.Flush();
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
}