Есть ли какой-нибудь инструмент, который может (довольно-печатать) формат XML файла, а также сортировать как его элементы, так и атрибуты?
Инструмент для сортировки и форматирования XML
Ответ 1
Я нашел этот пост: http://www.biglist.com/lists/xsl-list/archives/200106/msg01225.html, который использует следующий XSLT для отступов XML, а также сортирует атрибуты:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<!-- Sort the attributes by name. -->
<xsl:for-each select="@*">
<xsl:sort select="name( . )"/>
<xsl:copy/>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()|comment()|processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
Я еще не пробовал, но, скорее всего, я буду придерживаться XSLT для форматирования для меня.
Ответ 2
Мне понравился этот инструмент: https://xmlsorter.codeplex.com/
Вы можете сортировать по имени и атрибутам тегов. Мне нравится использовать его перед сравнением некоторых XML файлов.
Ответ 3
Я искал аналогичную утилиту и на самом деле не нашел то, что искал, поэтому я просто написал один вместо этого. Это очень просто (и не включает атрибуты в сортировке node), но работает.
Может быть, это будет полезно другим.. Это на GitHub.
Здесь немного от страницы GitHub...
USAGE: sortxml.exe [options] infile [outfile]
infile The name of the file to sort, etc.
outfile The name of the file to save the output to.
If this is omitted, then the output is written to stdout.
OPTIONS:
--pretty Ignores the input formatting and makes the output look nice.
--sort Sort both the nodes and attributes.
--sortnode Sort the nodes.
--sortattr Sort the attributes.
(prefix an option with ! to turn it off.)
По умолчанию используется вывод хороших и отсортированных узлов и атрибутов. Вот пример:
> type sample.xml
<?xml version="1.0" encoding="utf-8" ?><root><node value="one" attr="name"/></root>
> sortxml.exe sample.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<node attr="name" value="one" />
</root>
Ответ 4
Из-за неудовлетворенности 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, который в то же время написал кто-то другой. Я думаю, что это подходит легче/лучше в процессе сборки каждого. Но, может быть/надеюсь, это кому-нибудь пригодится.
Ответ 5
Я столкнулся с этим сообщением при попытке выяснить, как сортировать и редактировать файл edmx. Мое решение было основано на найденном решении Арво Боуэнса fooobar.com/info/426737/...
void Main()
{
XDocument xdoc = XDocument.Load(@"C:\git\Nvision\Source\NvisionEntities\NvisionModel.edmx");
Sort(xdoc.Root);
xdoc.Save(@"C:\git\Nvision\Source\NvisionEntities\NvisionModel.edmx");
}
public void Sort(XElement source, bool bSortAttributes = true)
{
//Make sure there is a valid source
if (source == null) throw new ArgumentNullException("source");
//Sort attributes if needed
if (bSortAttributes)
{
List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList();
sortedAttributes.ForEach(a => a.Remove());
sortedAttributes.ForEach(a => source.Add(a));
}
//Sort the children IF any exist
List<XElement> sortedChildren = source.Elements().OrderBy(elem => elem.Attributes("Name").Any() ? elem.Attributes("Name").First().Value.ToString() : string.Empty).ToList();
if (source.HasElements)
{
source.RemoveNodes();
sortedChildren.ForEach(c => Sort(c));
sortedChildren.ForEach(c => source.Add(c));
}
}