XElement保留属性顺序

时间:2016-01-08 16:28:29

标签: c# xml

我正在使用XDocument阅读以下文档:

<form>
    <hiddencontrols>
        <data classid="{5546E6CD-394C-4bee-94A8-4425E17EF6C6}" datafieldname="opportunityid" id="opportunityid"/>
        <data classid="{5546E6CD-394C-4bee-94A8-4425E17EF6C6}" datafieldname="producttypecode" id="producttypecode"/>
    </hiddencontrols>
</form>

示例加载:

XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xmlString));
XDocument xdoc = XDocument.Load(rdr, LoadOptions.None);
foreach (XElement xe in xdoc.Root.DescendantsAndSelf()) {
    if (xe.NodeType == XmlNodeType.Element) {
        if (xe.HasAttributes) {
             foreach (XAttribute xa in xe.Attributes()) {

在foreach中迭代属性,不保留原始XML中属性的原始顺序。也就是说,当我从foreach中再次写出属性时,它们将以与原始XML不同的顺序写出。

示例输出(仅第一个数据节点):

<data id="new_opportunityid" datafieldname="opportunityid" classid="{5546E6CD-394C-4bee-94A8-4425E17EF6C6}"/>

我试图确定是否应用了一些一致性(例如,XElement解析器是否总是以相反的顺序运行),属性顺序没有可辨别的模式。我还尝试使用XmlReader而不加载到XDocument,我尝试从XDocument而不是MemoryStream加载XmlReader。所有方法都会产生相同的结果。

我知道在XML规范中属性顺序并不重要,这对我很重要,因为我在foreach中进行属性值转换,我希望能够将最终文档与原始文档进行区分,而不必考虑到属性的不同排序,但只看到值的变化。它对于源代码控制中的差异大小也很重要。

2 个答案:

答案 0 :(得分:0)

嗯,这很奇怪。我今天早上随机找到了解决方案。这是我当前解析文档的设置顺序:

XDocument xdoc = XDocument.Parse(form.FormXml);
StringBuilder destXml = new StringBuilder();
XmlWriterSettings xrs = new XmlWriterSettings
{
    Indent = false,
    NewLineChars = String.Empty,
    WriteEndDocumentOnClose = true
};

XmlWriter xr = XmlWriter.Create(destXml, xrs);

我今天上午所做的更改是从Indent = false中的trueNewLineChars = String.Empty Environment.NewLine更改XmlWriterSettings。嘿presto,属性按照他们进入的顺序出现!!我不知道为什么会这样,但我已经测试了几次并且它是一致的......

答案 1 :(得分:-1)

xe.Attributes

返回C#中属性和集合的集合并不总是保留订单。

参考: Do C# collections always enforce order?

它说Enumerable.Select保留了订单。你可以亲自尝试一下吗?