XML сортировка / форматирование - PullRequest
14 голосов
/ 15 сентября 2009

Существует ли какой-либо инструмент, который может (довольно печатать) форматировать XML-файл, а также сортировать его элементы и атрибуты?

Ответы [ 5 ]

14 голосов
/ 12 июня 2014

Мне понравился этот инструмент: https://xmlsorter.codeplex.com/

Вы можете сортировать по имени тега и атрибутам. Мне нравится использовать его перед сравнением некоторых файлов XML.

XML Sorter main window

8 голосов
/ 25 января 2014

Я искал подобную утилиту и не нашел то, что искал, поэтому я просто написал ее. Это очень просто (и не включает атрибуты в сортировку узлов), но работает.

Может быть, это будет полезно для других .. Это на 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 голосов
/ 04 августа 2015

Из-за неудовлетворенности 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, который в то же время написал кто-то другой. Я думаю, что он вписался легче / лучше в процесс сборки каждого. Но, может быть / надеюсь, это кому-нибудь пригодится.

3 голосов
/ 16 сентября 2009

Я нашел этот пост: 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, чтобы выполнить форматирование для меня.

0 голосов
/ 18 сентября 2015

Я наткнулся на этот пост, когда пытался выяснить, как сортировать и редактировать файл. Мое решение было основано на найденном решении Arvo Bowens https://stackoverflow.com/a/19324438/212241

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));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...