2016-09-01 3 views
4

Ich habe Probleme mit dieser Sortierung und benötige ein wenig Hilfe.Sortierung mit LINQ

Ich werde Kindknoten entlang des Rangs sortieren und speichern. z.B. Um Unterknoten innerhalb des Hauptelements zu bestellen, gebe ich die ID für den spezifischen Abschnitt weiter.

Dieses Beispiel funktioniert nur für die ersten Nachkommen und jetzt steckte ich.

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); 

Ich brauche das.

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> 

Ziel

<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> 
+1

hilft ich Ihren Beitrag bearbeitet den Code korrekt zu formatieren und sie lesbar machen. Aber das '4x.Save (xmlString2);' war vorher da und ich ändere * code * beim Bearbeiten nicht. Ist das ein Tippfehler? –

+1

hast du Rekursion versucht? – slawekwin

Antwort

1

Ich glaube, Sie dort ein Tippfehler haben. Allerdings nehmen einen Blick auf diese Lösung:

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))); 

An diesem Punkt x enthält folgende 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> 

Wenn att gibt es anstelle von ‚opt` und sollten einbezogen werden, funktionieren folgende:

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))); 

wenn Sie mit dem Namen einzelnes Element sortieren müssen, verwenden Sie folgende (wenn kein Rang Attribut vorhanden ist oder leer ist, setzt auf der Rückseite):

+0

Vielen Dank für die schnelle Antwort. Ich werde es versuchen. – andy

+0

Ein weiteres Beispiel hinzugefügt. –

+0

?. ist ein bedingter Nullenoperator (https://msdn.microsoft.com/en-us/library/dn986595.aspx), um 'NullReferenceException' zu verhindern. Was ist der Fehler? –

0

Auch wenn dies keine direkte Antwort auf Ihr Problem ist, möchte ich Ihnen einen Weg vorschlagen, den direkten Umgang mit dem Xml über XDocument und verwandte Klassen zu vermeiden.

Wenn es um XML geht (wenn .xsd-Dateien nicht bereits vorhanden sind), tendiere ich dazu, manuelles Parsen zu vermeiden, indem ich die entsprechende .xsd erzeuge und daraus die benötigten Klassen erzeuge.

offen Visual Studio-Eingabeaufforderung:

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

(Beachten Sie, dass Sie die generierte XSD manuell besser kann anpassen, um Ihre Bedürfnisse anzupassen und zusätzliche spezifische contraints)

Die Klasse benötigten Informationen über die halten XML wird generiert.

Jetzt können Sie das gesamte XML in einem stark typisierten Objekt lesen, indem Sie die in der Datei .cs generierte Klasse verwenden.Sie müssen nur die .cs Datei in Ihrem Projekt importieren und die ursprüngliche XML deserialisieren:

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

Sie die XML-Speicher bearbeiten kann und zurück zu xml wie diese serialisiert:

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

StringXmlSerializer ist ein Helfer Ich Klasse schrieb ich, dass meine Bedürfnisse im Speicher auf einer Zeichenfolge serialisieren (aber Sie können direkt in einer Datei serialisieren). Ich poste den Code bekommen Sie auf, dass der Autor:

/// <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); 
    } 
} 

Hoffe, dass es jemand

Verwandte Themen