有没有一种工具可以对XML文件进行漂亮的格式化,并将其元素和属性排序?
有没有一种工具可以对XML文件进行漂亮的格式化,并将其元素和属性排序?
我在寻找一种类似的工具,但并没有找到我想要的,所以我自己写了一个。它非常简单(不包括节点排序中的属性),但很有效。
也许对其他人有用.. 它在 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>
我喜欢这个工具:https://xmlsorter.codeplex.com/
你可以按标签名称和属性进行排序。在比较一些XML文件之前,我喜欢使用它。
由于 Visual Studio 经常重新排序和重写 EDMX 文件(Entity Framework),让人感到沮丧(也可以参见此Uservoice),因此我编写了一些 Linqpad 代码来重新排序。然而,它很容易(并且很明显)在 LinqPad 之外使用。
它通过元素类型(标签)对元素进行排序,然后按元素属性“Name”的值进行排序,最后通过一些其他东西尝试使其具有确定性(不同的 XML,但是相同的含义通常会产生相同的输出 - 请参见代码)。
它还对属性进行排序。请注意,从语义上讲,XML 属性可能没有(相关的)顺序,但是从文本上讲,它们确实有顺序,并且版本控制系统仍然将它们视为纯文本...
(请注意,它不会修复在团队之间重新生成 Entity Framework edmx 文件时出现的不同别名问题)
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。我认为它更容易地/更好地适合每个人的构建过程。 但希望这对某些人有所帮助。
<thing> value </thing>
的节点中剥离值。 - CAD bloke<?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来进行格式化。
在尝试对 edmx 文件进行排序时,我遇到了这篇文章。我的解决方案基于 Arvo Bowens 的解决方案,该方案可以在以下链接中找到https://dev59.com/BXA75IYBdhLWcg3wGlIa#19324438。
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));
}
}