【发布时间】:2010-11-28 06:49:16
【问题描述】:
是否有任何工具可以(漂亮打印)格式化 XML 文件以及对其元素和属性进行排序?
【问题讨论】:
-
重复:stackoverflow.com/q/9161934/492 .. 但这里的答案对我更有用
标签: xml formatting
是否有任何工具可以(漂亮打印)格式化 XML 文件以及对其元素和属性进行排序?
【问题讨论】:
标签: xml formatting
由于 Visual Studio 似乎一直在重新排序和重写 EDMX 文件(实体框架)(另请参见 Uservoice),我写了一些 Linqpad 代码来重新排序东西。然而,在 LinqPad 之外使用它很容易(也很明显)。
它按元素类型(标签)对元素进行排序,然后是元素属性“名称”的值,然后是其他一些东西,试图使其具有确定性(不同的 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);
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>这样的节点中删除值
当我试图弄清楚如何排序和 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));
}
}
【讨论】:
我喜欢这个工具:https://xmlsorter.codeplex.com/
您可以按标签名称和属性进行排序。我喜欢在比较一些 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>
【讨论】:
我发现了这篇文章: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 为我进行格式化。
【讨论】: