Из-за неудовлетворенности Visual Studio, которая, кажется, постоянно переупорядочивает и переписывает EDMX-файлы (Entity Framework) (см. Также Uservoice ), я написал некоторый Linqpad-код для переупорядочения. Однако его легко (и очевидно) использовать за пределами LinqPad.
Упорядочивает элементы по типу элемента (тегу), затем по значению атрибута элемента «Имя», а затем по каким-то другим причинам, чтобы попытаться сделать его своего рода детерминированным (другой xml, но с тем же значением, [обычно] один и тот же вывод - см. код).
Также заказывает атрибуты. Обратите внимание, что семантически XML-атрибуты могут не иметь (релевантного) порядка, но текстуально они имеют, и системы контроля версий по-прежнему считают их текстовыми ...
(Обратите внимание, что он не исправляет различные псевдонимы, упомянутые в Файл edmx Entity Framework, восстанавливающийся по-разному в команде )
void Main()
{
XDocument xdoc = XDocument.Load(@"\\filepath1\file1.edmx");
var orderedElements = CopyAndSortElements(xdoc.Elements());
var newDoc = new XDocument();
newDoc.Add(orderedElements);
newDoc.Save(@"\\filepath1\file1.Ordered.edmx");
}
public IEnumerable<XElement> CopyAndSortElements(IEnumerable<XElement> elements)
{
var newElements = new List<XElement>();
// Sort XElements by Tag & name-attribute (and some other properties)
var orderedElements = elements.OrderBy(elem => elem.Name.LocalName) // element-tag
.ThenByDescending(elem => elem.Attributes("Name").Count()) // can be 0, more than 1 is invalid XML
.ThenBy(elem => (elem.Attributes("Name").Any() ? elem.Attributes("Name").First().Value.ToString() : string.Empty))
// in case of no Name-Attributes, try to sort by (number of) children
.ThenBy(elem => elem.Elements().Count())
.ThenBy(elem => elem.Attributes().Count())
// next line may vary for textually different but semantically equal input when elem & attr were unordered on input, but I need to restrain myself...
.ThenBy(elem => elem.ToString());
foreach (var oldElement in orderedElements)
{
var newElement = new XElement(oldElement.Name);
if (oldElement.HasElements == false && string.IsNullOrEmpty(oldElement.Value) == false)
{
// (EDMX does not have textual nodes, but SO-users may use it for other XML-types ;-) )
// IsNullOrEmpty-check: not setting empty value keeps empty-element tag, setting value (even empty) causes start-tag immediately followed by an end-tag
// (empty-element tags may be a matter of taste, but for textual comparison it will matter!)
newElement.Value = oldElement.Value;
}
var orderedAttrs = oldElement.Attributes().OrderBy(attr => attr.Name.LocalName).ThenBy(attr => attr.Value.ToString());
newElement.Add(orderedAttrs);
newElement.Add(CopyAndSortElements(oldElement.Elements()));
newElements.Add(newElement);
}
return newElements;
}
PS: В итоге мы использовали XSLT, который в то же время написал кто-то другой. Я думаю, что он вписался легче / лучше в процесс сборки каждого.
Но, может быть / надеюсь, это кому-нибудь пригодится.