Sorting with LINQ

I am struggling with this sorting and need a little help.

I will sort the child nodes along the rank and save it. for example, to order auxiliary nodes inside the main element, I will pass the identifier for a particular section.

This example only works for the first descendants, and now I'm stuck.

XElement x = XElement.Load(xmlString1);
x.Descendants("opt").First().ReplaceNodes(x.Descendants("opt").First()
 .Descendants("sel").OrderBy(o => int.Parse(o.Attribute("rank").Value)));
4x.Save(xmlString2);

I need it.

x.Descendants("sub").Where(b => b.Attribute("id").Value == "DFG")
 .ReplaceNodes(x.Descendants("opt").First()
 .Descendants("sel").OrderBy(o => int.Parse(o.Attribute("rank").Value))

Original

  <main id="AFB" rank="1" name="ROOT">
<sub id="DFG" rank="2" name="SUB1">
 <att >
    <sel id="JIK" rank="4" name="444" />
    <sel id="OKI" rank="2" name="222" />
  </att>
  <opt>
    <sel id="JIK" rank="2" name="122" />
    <sel id="OKI" rank="1" name="111" />
  </opt>
</sub>  
 <sub id="EGG" rank="1" name="SUB2" >
  <opt>
    <sel id="DJI" rank="1" name="111" />
    <sel id="LOW" rank="3" name="333" />
    <sel id="QWE" rank="2" name="222" />
  </opt>
</sub>
<main>

Target

 <main id="AFB" rank="1" name="ROOT">   
 <sub id="EGG" rank="1" name="SUB2" >
  <opt>
    <sel id="DJI" rank="1" name="111" />        
    <sel id="QWE" rank="2" name="222" />
    <sel id="LOW" rank="3" name="333" />
  </opt>
</sub>
<sub id="DFG" rank="2" name="SUB1">
  <att >
    <sel id="OKI" rank="2" name="222" />
    <sel id="JIK" rank="4" name="444" />        
  </att>
  <opt>
    <sel id="OKI" rank="1" name="111" />
    <sel id="JIK" rank="2" name="122" />        
  </opt>
</sub>
<main>
+4
source share
2 answers

I think you have typos there. However, take a look at this solution:

var text = @"
<main id='AFB' rank='1' name='ROOT'>
    <sub id='DFG' rank='2' name='SUB1'>
        <opt>
            <sel id='JIK' rank='4' name='444' />
            <sel id='OKI' rank='2' name='222' />
        </opt>
        <opt>
            <sel id='JIK' rank='2' name='122' />
            <sel id='OKI' rank='1' name='111' />
        </opt>
    </sub>  
    <sub id='EGG' rank='1' name='SUB2' >
        <opt>
            <sel id='DJI' rank='1' name='111' />
            <sel id='LOW' rank='3' name='333' />
            <sel id='QWE' rank='2' name='222' />
        </opt>
    </sub>
</main>";

var x = XDocument.Parse(text);
x.Root.ReplaceNodes(x.Descendants("sub").OrderBy(a => int.Parse(a.Attribute("rank").Value)));
foreach (var opt in x.Descendants("opt"))
    opt.ReplaceNodes(opt.Descendants("sel").OrderBy(a => int.Parse(a.Attribute("rank").Value)));

At this point, it xcontains the following XML:

<main id="AFB" rank="1" name="ROOT">
  <sub id="EGG" rank="1" name="SUB2">
    <opt>
      <sel id="DJI" rank="1" name="111" />
      <sel id="QWE" rank="2" name="222" />
      <sel id="LOW" rank="3" name="333" />
    </opt>
  </sub>
  <sub id="DFG" rank="2" name="SUB1">
    <opt>
      <sel id="OKI" rank="2" name="222" />
      <sel id="JIK" rank="4" name="444" />
    </opt>
    <opt>
      <sel id="OKI" rank="1" name="111" />
      <sel id="JIK" rank="2" name="122" />
    </opt>
  </sub>
</main>

If attthere is instead of "opt" and should be enabled, the following will work:

var x = XDocument.Parse(text);
x.Root.ReplaceNodes(x.Descendants("sub").OrderBy(a => int.Parse(a.Attribute("rank").Value)));
foreach (var opt in x.Descendants("sub").Elements())
    opt.ReplaceNodes(opt.Descendants("sel").OrderBy(a => int.Parse(a.Attribute("rank").Value)));

, ( , ):

//sub with id=EGG
var sub2 = x.Descendants("sub").FirstOrDefault(a => a.Attribute("id").Value == "EGG");
if (sub2 != null)
{
    foreach (var node in sub2.Elements())
        node.ReplaceNodes(node.Elements().OrderBy(a =>
        {
            int rank;
            if (a.Attribute("rank") == null || !int.TryParse(a.Attribute("rank").Value, out rank))
                rank = int.MaxValue;
            return rank;
        }));
}
+1

, Xml XDocument .

xml ( .xsd ), , .xsd , xml.

:

   -> xsd "yourxml.xml" (a .xsd file will be generated)
   -> xsd /c "yourxml.xsd" (a .cs file will be generated)

( , , , xsd, )

, xml.

xml , , .cs. .cs xml:

string fileContent = File.ReadAllText( fileLocation );
var xmlObj = StringXmlSerializer.XmlDeserialize<YourXsdGeneratedType>( fileContent );

xml xml :

string xmlContext = StringXmlSerializer.XmlSerialize( xmlObj );
File.WriteAllText( filePath, xmlObj );

StringXmlSerializer - i, , ( ). , :

/// <summary>
/// Serialize object in xml format on a string
/// </summary>
public static class StringXmlSerializer
{
    public static string XmlSerialize( object objectInstance )
    {
        XmlWriterSettings ws = new XmlWriterSettings();
        ws.NewLineHandling = NewLineHandling.Entitize;

        var serializer = new XmlSerializer( objectInstance.GetType() );
        var sb = new StringBuilder();

       using( XmlWriter xmlWriter = XmlWriter.Create( sb, ws ) )
           serializer.Serialize( xmlWriter, objectInstance );

        return sb.ToString();
    }

    public static T XmlDeserialize<T>( string objectData )
    {
        return (T)XmlDeserialize( objectData, typeof( T ) );
    }

    public static object XmlDeserialize( string objectData, Type type )
    {
        var serializer = new XmlSerializer( type );

        using( TextReader reader = new StringReader( objectData ) )
            return serializer.Deserialize( reader );
    }
}

, -

0

Source: https://habr.com/ru/post/1653289/


All Articles