代码之家  ›  专栏  ›  技术社区  ›  Andrey Adamovich

XML排序/格式化工具

  •  14
  • Andrey Adamovich  · 技术社区  · 15 年前

    是否有任何工具可以(漂亮地打印)格式化XML文件以及对其元素和属性进行排序?

    5 回复  |  直到 9 年前
        1
  •  14
  •   Akira Yamamoto    11 年前

    我喜欢这个工具: https://xmlsorter.codeplex.com/

    可以按标记名和属性排序。我喜欢在比较一些XML文件之前使用它。

    XML Sorter main window

        2
  •  8
  •   kodybrown    11 年前

    我正在寻找一个类似的实用程序,并没有真正找到我要找的,所以我只写了一个代替。它非常简单(并且在节点排序中不包括属性),但是可以工作。

    也许对其他人有用……这是关于 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>
    
        3
  •  3
  •   Andrey Adamovich    15 年前

    我找到了这个帖子: 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来为自己设置格式。

        4
  •  3
  •   Community CDub    8 年前

    出于对Visual Studio的失望,它似乎一直在重新排序和重写EDMX文件(实体框架)(另请参见 Uservoice ,我写了一些LinqPad代码来重新排序。但是,在LinqPad之外使用起来很容易(也很明显)。

    它按元素类型(标记)对元素排序,然后按元素属性“name”的值排序,然后按其他一些东西排序,以使其具有某种确定性(不同的XML,但含义相同,通常是相同的输出-请参见代码)。

    它还对属性进行排序。注意 语义上 XML属性可能没有(相关)顺序,但 文本地 是的,版本控制系统仍然认为它们是纯文本的…

    (请注意,它不会修复中提到的不同别名 Entity Framework edmx file regenerating differently amongst team )

    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);
            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;
    }
    

    附:我们最终使用了一个XSLT,其他人同时编写了它。我认为它更适合每个人的建造过程。 但也许/希望这对某些人有用。

        5
  •  0
  •   Community CDub    8 年前

    当我试图弄清楚如何排序和EDMX文件时,我偶然看到了这篇文章。 我的解决方案是基于找到的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));
        }
    }