C#xml文件按ID排序标签,但保存相同的名称顺序

时间:2019-11-13 16:19:27

标签: c# xml linq sorting

我试图只按ID在相同名称标签之间对xml标签进行排序,所以我想在其子元素中进行相同的处理。现在,我只能对根的第一级进行排序。有什么想法可以使它更有效吗?

谢谢您的建议。

之前的示例:

<AFDatabase>
        <Element1><id>1</id></Element1>
        <Element1><id>10</id></Element1>
        <Element1><id>5</id></Element1>
        <Element1><id>4</id>
    <ElementInside><id>3</id><ElementInside>
    <ElementInside><id>2</id><ElementInside>
    <ElementInside><id>1</id><ElementInside>
    <ElementInside><id>0</id><ElementInside>
    <ElementInside4><id>3</id><ElementInside4>
    <ElementInside4><id>2</id><ElementInside4>
    <ElementInside4><id>1</id><ElementInside4>
    <ElementInside2><id>3</id><ElementInside2>
    <ElementInside2><id>2</id><ElementInside2>
    <ElementInside2><id>1</id><ElementInside2>
    </Element1>            

//// AFTER ///

<AFDatabase>
    <Element1><id>1</id></Element1>
    <Element1><id>4</id>

    <ElementInside><id>0</id><ElementInside>
    <ElementInside><id>1</id><ElementInside>
    <ElementInside><id>2</id><ElementInside>
    <ElementInside><id>3</id><ElementInside>
    <ElementInside4><id>1</id><ElementInside4>
    <ElementInside4><id>2</id><ElementInside4>
    <ElementInside4><id>3</id><ElementInside4>
    <ElementInside2><id>1</id><ElementInside2>
    <ElementInside2><id>2</id><ElementInside2>
    <ElementInside2><id>3</id><ElementInside2>

    </Element1>
    <Element1><id>5</id></Element1>
    <Element1><id>10</id></Element1>

</AFDatabase>

代码

 private static XElement xmlSorting(XElement root)
            {

                var xmlStruct = sortRootBYID(root);



                return new XElement(root.Name,
                        root.Attributes(), new XElement("AFDatabase",

                        from child in root.Nodes()
                        where child.NodeType != XmlNodeType.Element
                        select child,

                        from child in xmlStruct.Elements()
                        select child));


            }

            private static XElement sortRootBYID(XElement root)
            {
               var ElementNames =  getElementNames(root);


                var xmlStruct = new XElement("x");
                xmlStruct.RemoveAll();
                foreach (var elementName in ElementNames)
                {

                    var orderedTags = root.Elements("AFDatabase").Elements(elementName)
                                           .OrderBy(xtab => (string)xtab.Element("id"))
                                           .ToArray();

                    foreach (XElement tag in orderedTags)
                        xmlStruct.Add(tag);


                }

                return xmlStruct;


            }

            private static HashSet<string> getElementNames (XElement root)
            {
                HashSet<string> ElementNames = new HashSet<string>();
                foreach (var element in root.Elements().Elements())
                {
                    //Console.WriteLine();


                    if (element.Name != null)
                    {
                        ElementNames.Add(element.Name.ToString());
                    }
                }



                return ElementNames;
            }

1 个答案:

答案 0 :(得分:0)

实现此目的的一种方法如下。您需要先对“第一级”元素进行排序,然后再根据“元素名称”对内部元素进行分组,然后对其进行排序。

var xDoc = XDocument.Parse(xml);
var elementCollection = xDoc.Root.Elements("Element1")
                          .OrderBy(x=> int.Parse(x.Element("id").Value)).ToList();

foreach(var element in elementCollection.Where(x=>x.Descendants().Any(c=>c.Name.LocalName.StartsWith("ElementInside"))).ToArray())
{
    var innerElements = element.Descendants()
                         .Where(x=>!x.Name.LocalName.Equals("id"))
                         .GroupBy(x=>x.Name.LocalName)
                         .Select(x=>x.ToList().OrderBy(c=>c.Element("id") == null ? "0" : c.Element("id").Value))
                         .SelectMany(x=>x).ToList();
    innerElements.Insert(0,element.Element("id"));
    element.ReplaceAll(innerElements);
}
var result = new XElement("AFDatabase", elementCollection);

Demo Code