2016-06-27 15 views
0

Ich versuche zu lernen, XML-Dateien in meiner Anwendung zu verwenden. Ich möchte ein Element einfach lesen und optional ein Element neu schreiben und seinen Wert erhalten. Ich habe eine XML-Datei, die etwas wie folgt aussieht:Lesen und Schreiben eines einfachen Elements in xml

<?xml version="1.0" encoding="utf-16"?> 
<PTH> 
    <Account> 
    <Username>aa</Username> 
    <Password>xx</Password> 
    <Email>[email protected]</Email> 
    <Role>Student</Role> 
    </Account> 
    <ChartName> 
    <Id>1</Id> 
    <Name>John Smith</Name> 
    <PlaceOfBirth>louisville, ky</PlaceOfBirth> 
    <BirthDate>1/1/70</BirthDate> 
    <TimeZone>Greenwich</TimeZone> 
    </ChartName> 
    <ChartName> 
    <Id>2</Id> 
    <Name>John Smith</Name> 
    <PlaceOfBirth>New York, NY</PlaceOfBirth> 
    <BirthDate>1/1/1980</BirthDate> 
    <TimeZone>Greenwich</TimeZone> 
    </ChartName> 
    <ChartName> 
    <Id>3</Id> 
    <Name>Jane Doe</Name> 
    <PlaceOfBirth>Los Angeles, Ca</PlaceOfBirth> 
    <BirthDate>1/1/1990</BirthDate> 
    <TimeZone>Greenwich</TimeZone> 
    </ChartName> 
</PTH> 

Wo nur ein Konto Element und mehrere Elemente chartname sein wird. Der Code, den ich herauskam, ist:

public class Account 
{ 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public string Email { get; set; } 
    public string Role { get; set; } 
} 

... 

    XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath("~") + "\\App_Data\\" + username.Text.Trim()); 
    XElement xEle = xml.Element("PTH"); 

    var Accounts = (from Account in xml.Root.Elements("Account") 
        select new 
        { 
         Email = (string)Account.Element("Email").Value, 
         Role = (string)Account.Element("Role").Value 
        }); 
    foreach (var Account in Accounts) 
    { 
     Session["Email"] = Account.Email; 
     Session["Role"] = Account.Role; 
    } 

Der Code funktioniert, aber es scheint ein wirklich, wirklich gewundenen Weg, um nur die Werte eines Elements zu lesen. Außerdem bin ich mir nicht ganz sicher, wie ich zum Beispiel nur den Wert des E-Mail-Elements umschreiben kann. Hat jemand eine sehr einfache Möglichkeit, einen Elementwert zu lesen und/oder neu zu schreiben? Es scheint, dass es sehr einfach sein sollte, aber es entgeht mir ...

+0

wenn es nur 1 'Account' Knoten gibt, warum die' foreach' und Linq? Ich denke, Sie können XPath verwenden und nur die einzelnen Knoten auswählen, um ihre Werte zu erhalten (InnerText). [Referenz] (https://msdn.microsoft.com/en-us/library/h0hw012b (v = vs.110) .aspx) – zgood

+0

Ja, die 'Foreach' scheint wie Overkill, aber das ist, was ich in der gefunden habe Tutorials, die ich gelesen hatte. Die meisten Tutorials zeigen einfache XML-Dateien mit nur einem Typ von Hauptelementen wie zum Beispiel 'Buch' und nicht Dateien mit mehreren Elementtypen. – SteveFerg

+0

Haben Sie Kontrolle über das XML-Format? Wenn die Elemente in einem übergeordneten Element eingeschlossen wären, wäre es serialisierbar. – Derpy

Antwort

1

Ich habe dieses Beispiel für Sie ausgeschrieben. Es sind nur 6 Zeilen, und es liest und schreibt in ein XML-Dokument.

Ich habe Kommentare hinzugefügt, die erklären, was vor sich geht.

 // this loads up your XDocument. your XDocument is an object which represents your xml file. 
     XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath("~") + "\\App_Data\\" + username.Text.Trim()); 

     // this is a quick and dirty way to get the all of the elements element named "Email" 
     // don't worry too much about "var" it's still strongly typed, and is just a syntatical shortcut so I dont' have to actually type out 
     // the name of whatever type xml.Descendant returns. 
     var emails = xml.Descendants("Email"); 

     // if you want just one, use "First" 
     var firstEmail = emails.First(); 

     // if you want the value, use the ".Value" property 
     Console.WriteLine(firstEmail.Value); 

     // if you want to change it, use normal assignment, and 
     firstEmail.Value = "[email protected]"; 

     // if you want to persist your changes to disk, save your document. 
     xml.Save("C:\\temp\\otherfolder\\xmldocument.xml"); 

Wenn Sie noch mehr Kürzeln möchten, können Sie bei This answer über schauen, wie XPath syntax zu verwenden (die Antwort ist etwas veraltet, dass der Namespace Sie jetzt verwenden, ist using System.Xml.XPath;

1

Wenn Sie die Kontrolle über die XML haben Format, ich finde Serialisierung zu einem zivilisierteren Ansatz zum Parsen von XML.JSON ist eigentlich mein Format der Wahl, aber XML funktioniert auch.Wenn Sie eine Präferenzen Eigenschaft später hinzufügen möchten, können Sie es einfach zu Ihrer PTH-Klasse hinzufügen.

private void Test() 
    { 
     var obj = new PTH() 
     { 
      Account = new Account() { UserName = "bob's", Password = "burgers" }, 
      ChartNames = Enumerable.Range(1, 3).Select(x => new ChartName() { Id = x, name = "Name_" + x.ToString() }).ToArray() 
     }; 
     var xml = SerializeXML(obj); 
     var objDeserialized = DeserializeXML<PTH>(xml); 
     var chartsToChange = objDeserialized.ChartNames.Where(x => x.Id == 1).ToList(); 
     foreach (var chart in chartsToChange) 
     { 
      chart.name = "new name"; 
     } 

     var backToXML = SerializeXML(objDeserialized); 
    } 

    public static string SerializeXML<T>(T obj) 
    { 
     var izer = new System.Xml.Serialization.XmlSerializer(typeof(T)); 

     using (var stringWriter = new StringWriter()) 
     { 
      using (var xmlWriter = new XmlTextWriter(stringWriter)) 
      { 
       izer.Serialize(xmlWriter, obj); 
       return stringWriter.ToString(); 
      } 
     } 
    } 

    public static T DeserializeXML<T>(string xml) 
    { 
     var izer = new System.Xml.Serialization.XmlSerializer(typeof(T)); 

     using (var stringReader = new StringReader(xml)) 
     { 
      using (var xmlReader = new XmlTextReader(stringReader)) 
      { 
       return (T)izer.Deserialize(xmlReader); 
      } 
     } 
    } 
    public class PTH 
    { 
     public Account Account { get; set; } 
     public ChartName[] ChartNames { get; set; } 
    } 
    public class Account 
    { 
     public string UserName { get; set; } 
     public string Password { get; set; } 
    } 

    public class ChartName 
    { 
     public int Id { get; set; } 
     public string name { get; set; } 
    } 

Das XML ist nicht viel anders, nur dass die Array-Elemente einen übergeordneten Knoten benötigen.

<?xml version="1.0" encoding="UTF-8"?> 
<PTH xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Account> 
     <UserName>bob's</UserName> 
     <Password>burgers</Password> 
    </Account> 
    <ChartNames> 
     <ChartName> 
     <Id>1</Id> 
     <name>Name_1</name> 
     </ChartName> 
     <ChartName> 
     <Id>2</Id> 
     <name>Name_2</name> 
     </ChartName> 
     <ChartName> 
     <Id>3</Id> 
     <name>Name_3</name> 
     </ChartName> 
    </ChartNames> 
</PTH> 
+0

Das gibt mir eine andere Möglichkeit, es zu betrachten. Wenn ich anfange, die astrologischen Diagramme zu betrachten, wird das meiste Lesen/Schreiben in den Diagrammnamen sein. Ich schreibe die für die Verarbeitung benötigten Utility-Funktionen, daher ist diese Lösung sehr hilfreich. Vielen Dank. – SteveFerg

Verwandte Themen