XML-String in Objekt konvertieren

179

Ich empfange XML-Zeichenfolgen über einen Socket und möchte diese in C # -Objekte konvertieren.

Die Nachrichten haben die Form:

<msg>
   <id>1</id>
   <action>stop</action>
</msg>

Ich bin neu in .Net und bin mir nicht sicher, wie ich dies am besten durchführen kann. Ich habe JAXB für Java bereits verwendet und war mir nicht sicher, ob es etwas Ähnliches gibt oder ob dies anders gehandhabt wird.

Steve
quelle
3
Haben Sie Objekte, zu denen diese werden, oder möchten Sie die Objekte dynamisch generieren?
Stephan
Suchen Sie nach diesem Beitrag: http://stackoverflow.com/questions/765422/jaxb-equivalent-in-c
Aykut Çevik
Für mich war dies die beste Option: stackoverflow.com/a/24184283/2647430
Ivan Lopez

Antworten:

276

Sie müssen das xsd.exeTool, das mit dem Windows SDK installiert wird, in einem ähnlichen Verzeichnis verwenden:

C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin

Und auf 64-Bit-Computern:

C:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\bin

Und auf Windows 10-Computern:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin

Beim ersten Durchlauf verwenden xsd.exeSie Ihr Beispiel-XML und konvertieren es in eine XSD-Datei (XML-Schemadatei):

xsd yourfile.xml

Dies gibt Ihnen yourfile.xsd, was Sie in einem zweiten Schritt erneut mit xsd.exein eine C # -Klasse konvertieren können :

xsd yourfile.xsd /c

Dies sollte Ihnen eine Datei yourfile.csgeben, die eine C # -Klasse enthält, mit der Sie die XML-Datei, die Sie erhalten, deserialisieren können - etwa:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
msg resultingMessage = (msg)serializer.Deserialize(new XmlTextReader("yourfile.xml"));

Sollte in den meisten Fällen ziemlich gut funktionieren.

Update: Der XML-Serializer nimmt jeden Stream als Eingabe - entweder eine Datei oder ein Speicher-Stream ist in Ordnung:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(inputString));
msg resultingMessage = (msg)serializer.Deserialize(memStream);

oder verwenden Sie einen StringReader:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
StringReader rdr = new StringReader(inputString);
msg resultingMessage = (msg)serializer.Deserialize(rdr);
marc_s
quelle
Danke für die ausführliche Erklärung. In meinem Fall kommt das XML über einen Socket und ist eine Zeichenfolge. Wie würde ich eine Zeichenfolge anstelle einer XML-Datei de-serialisieren?
Steve
5
@Steve: Sie können einen StringReader öffnen und die Deserialize-Methode übergeben. StringReader leitet sich von TextReader ab.
Skurmedel
Würden Sie Ihren Ansatz demjenigen vorziehen, den Fahad mit Linq erwähnt hat?
Steve
2
@Steve: Ja, ich würde - das Deserialisieren in ein Objekt und das Stöbern in den Eigenschaften des Objekts scheint viel einfacher zu sein, als viel mit XML-Elementen, Attributen, untergeordneten Knoten usw. zu wackeln. Linq-to-XML ist großartig, wenn das XML ist unregelmäßig und ändert sich ständig oder ist nicht im Voraus bekannt.
marc_s
7
Diese Website ist viel einfacher als das xsd-Tool IMO: xmltocsharp.azurewebsites.net
nasch
226

Sie haben zwei Möglichkeiten.

Methode 1. XSD- Tool


Angenommen, Sie haben Ihre XML-Datei an diesem Speicherort C:\path\to\xml\file.xml

  1. Öffnen Sie die Eingabeaufforderung für Entwickler.
    Sie finden sie in. Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Wenn Sie Windows 8 verwenden, können Sie einfach die Eingabeaufforderung für Entwickler in den Startbildschirm eingeben
  2. Ändern Sie den Speicherort in Ihr XML-Dateiverzeichnis, indem Sie Folgendes eingeben cd /D "C:\path\to\xml"
  3. Erstellen Sie eine XSD-Datei aus Ihrer XML-Datei, indem Sie Folgendes eingebenxsd file.xml
  4. Erstellen Sie C # -Klassen durch Eingabexsd /c file.xsd

Und das ist es! Sie haben C # -Klassen aus der XML-Datei in generiertC:\path\to\xml\file.cs

Methode 2 - Spezial einfügen


Erforderliches Visual Studio 2012+ mit .Net Framework> = 4.5 als Projektziel und installierter einzelner Komponente von 'Windows Communication Foundation'

  1. Kopieren Sie den Inhalt Ihrer XML-Datei in die Zwischenablage
  2. Fügen Sie Ihrer Lösung eine neue, leere Klassendatei hinzu ( Shift+ Alt+ C)
  3. Öffnen Sie diese Datei und klicken Sie im Menü auf Edit > Paste special > Paste XML As Classes
    Geben Sie hier die Bildbeschreibung ein

Und das ist es!

Verwendung


Die Verwendung dieser Hilfsklasse ist sehr einfach:

using System;
using System.IO;
using System.Web.Script.Serialization; // Add reference: System.Web.Extensions
using System.Xml;
using System.Xml.Serialization;

namespace Helpers
{
    internal static class ParseHelpers
    {
        private static JavaScriptSerializer json;
        private static JavaScriptSerializer JSON { get { return json ?? (json = new JavaScriptSerializer()); } }

        public static Stream ToStream(this string @this)
        {
            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);
            writer.Write(@this);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }


        public static T ParseXML<T>(this string @this) where T : class
        {
            var reader = XmlReader.Create(@this.Trim().ToStream(), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
            return new XmlSerializer(typeof(T)).Deserialize(reader) as T;
        }

        public static T ParseJSON<T>(this string @this) where T : class
        {
            return JSON.Deserialize<T>(@this.Trim());
        }
    }
}

Jetzt müssen Sie nur noch Folgendes tun:

    public class JSONRoot
    {
        public catalog catalog { get; set; }
    }
    // ...

    string xml = File.ReadAllText(@"D:\file.xml");
    var catalog1 = xml.ParseXML<catalog>();

    string json = File.ReadAllText(@"D:\file.json");
    var catalog2 = json.ParseJSON<JSONRoot>();
Damian Drygiel
quelle
7
Prost. Zu Methode 2 müssen Sie auf .net 4.5 abzielen, sonst ist die Option nicht verfügbar.
TimB33
12
Methode 2 ist lächerlich nützlich! Dank dafür. Ich hatte keine Ahnung, dass es das gab.
Dominic Bindley
1
Ein großes Lob für die Methode 2, wirkt wie ein Zauber. Hervorragend geeignet, wenn Sie versuchen, ein XML einfach programmgesteuert zu analysieren, ohne langweilige Klassen implementieren zu müssen.
Alex
1
Sie sollten "Paste Special" als erste Methode festlegen - es ist die einfachste. Einschränkung ".Net Framework> = 4.5" ist 2017 nicht wichtig.
Michael Freidgeim
2
Für "XML als Klassen einfügen" muss die WCF-Workload für Visual Studio installiert sein.
Lennart
49

Versuchen Sie diese Methode, um XML in ein Objekt zu konvertieren. Es ist genau für das gemacht, was Sie tun:

protected T FromXml<T>(String xml)
{
    T returnedXmlClass = default(T);

    try
    {
        using (TextReader reader = new StringReader(xml))
        {
            try
            {
                returnedXmlClass = 
                    (T)new XmlSerializer(typeof(T)).Deserialize(reader);
            }
            catch (InvalidOperationException)
            {
                // String passed is not XML, simply return defaultXmlClass
            }
        }
    }
    catch (Exception ex)
    {
    }

    return returnedXmlClass ;        
}

Nennen Sie es mit diesem Code:

YourStrongTypedEntity entity = FromXml<YourStrongTypedEntity>(YourMsgString);
RJ.
quelle
6
Erhielt diesen Fehler xmlns = ''> wurde nicht erwartet. "},
Prashant
Das Problem ist, dass Sie Ihre Klasse im Voraus perfekt zusammenstellen müssen. Vielleicht eine Funktion, die eine Klasse ausgibt, wenn XML angegeben wird? xsd.exe ist Hit & Miss (meistens Miss für komplexe Sachen) ...
Yumi Koizumi
1
Oh mein Gott, ich habe Stunden damit verbracht, mich mit .nets xml serializer zu beschäftigen, und das hat sofort funktioniert.
Christopher Clark
11

Führen Sie einfach Visual Studio 2013 als Administration aus ... Kopieren Sie den Inhalt Ihrer XML-Datei. Gehen Sie zu Visual Studio 2013> Bearbeiten> Inhalte einfügen> XML als C # -Klassen einfügen. Dadurch werden Ihre C # -Klassen entsprechend dem Inhalt Ihrer XML-Datei erstellt.

user2667652
quelle
7

Nur für den Fall, dass jemand dies nützlich finden könnte:

public static class XmlConvert
{
    public static string SerializeObject<T>(T dataObject)
    {
        if (dataObject == null)
        {
            return string.Empty;
        }
        try
        {
            using (StringWriter stringWriter = new System.IO.StringWriter())
            {
                var serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stringWriter, dataObject);
                return stringWriter.ToString();
            }
        }
        catch (Exception ex)
        {
            return string.Empty;
        }
    }

    public static T DeserializeObject<T>(string xml)
         where T : new()
    {
        if (string.IsNullOrEmpty(xml))
        {
            return new T();
        }
        try
        {
            using (var stringReader = new StringReader(xml))
            {
                var serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(stringReader);
            }
        }
        catch (Exception ex)
        {
            return new T();
        }
    }
}

Sie können es aufrufen mit:

MyCustomObject myObject = new MyCustomObject();
string xmlString = XmlConvert.SerializeObject(myObject)
myObject = XmlConvert.DeserializeObject<MyCustomObject>(xmlString);
Razzer
quelle
5

Sie können eine Klasse wie oben beschrieben generieren oder manuell schreiben:

[XmlRoot("msg")]
public class Message
{
    [XmlElement("id")]
    public string Id { get; set; }
    [XmlElement("action")]
    public string Action { get; set; }
}

Anschließend können Sie ExtendedXmlSerializer zum Serialisieren und Deserialisieren verwenden.

Installation Sie können ExtendedXmlSerializer von Nuget installieren oder den folgenden Befehl ausführen:

Install-Package ExtendedXmlSerializer

Serialisierung:

var serializer = new ConfigurationContainer().Create();
var obj = new Message();
var xml = serializer.Serialize(obj);

Deserialisierung

var obj2 = serializer.Deserialize<Message>(xml);

Diese Serializer-Unterstützung:

  • Deserialisierungs-XML aus dem Standard-XMLSerializer
  • Serialisierungsklasse, Struktur, generische Klasse, primitiver Typ, generische Liste und Wörterbuch, Array, Aufzählung
  • Serialisierungsklasse mit Eigenschaftsschnittstelle
  • Serialisierungszirkelreferenz und Referenz-ID
  • Deserialisierung der alten XML-Version
  • Eigenschaftsverschlüsselung
  • Benutzerdefinierter Serializer
  • Unterstützt XmlElementAttribute und XmlRootAttribute
  • POCO - Alle Konfigurationen (Migrationen, benutzerdefinierter Serializer ...) befinden sich außerhalb der Klasse

ExtendedXmlSerializer unterstützt .NET 4.5 oder höher und .NET Core . Sie können es in WebApi und AspCore integrieren.

Wojtpl2
quelle
1
Ausgezeichnete Post! Ich habe den Code aktualisiert, um ihn gemäß der Dokumentation github.com/wojtpl2/ExtendedXmlSerializer
user1477388
2

Damians großartige Antwort vereinfachen,

public static T ParseXml<T>(this string value) where T : class
{
    var xmlSerializer = new XmlSerializer(typeof(T));
    using (var textReader = new StringReader(value))
    {
        return (T) xmlSerializer.Deserialize(textReader);
    }
}
Sam Jazz
quelle
1

Erstellen Sie ein DTO als CustomObject

Verwenden Sie die folgende Methode, um XML-Zeichenfolgen mit JAXB in DTO zu konvertieren

private static CustomObject getCustomObject(final String ruleStr) {
    CustomObject customObject = null;
    try {
        JAXBContext jaxbContext = JAXBContext.newInstance(CustomObject.class);
        final StringReader reader = new StringReader(ruleStr);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        customObject = (CustomObject) jaxbUnmarshaller.unmarshal(reader);
    } catch (JAXBException e) {
        LOGGER.info("getCustomObject parse error: ", e);
    }
    return customObject;
}
Mohit Singh
quelle
0

Wenn Sie die xsd der xml-Nachricht haben, können Sie mit dem Tool .Net xsd.exe c # -Klassen generieren.

Diese .Net-Klassen können dann zum Generieren der XML verwendet werden.

Amitabh
quelle
0

Zusätzlich zu den anderen Antworten hier können Sie natürlich die XmlDocument- Klasse zum Lesen von XML- DOMs oder den XmlReader -Reader nur für den schnellen Vorlauf verwenden, um dies "von Hand" zu tun.

Skurmedel
quelle
0

Eine andere Möglichkeit mit einem erweiterten Tool zur Generierung von xsd zu c # -Klassen: xsd2code.com. Dieses Tool ist sehr praktisch und leistungsstark. Es hat viel mehr Anpassungsmöglichkeiten als das Tool xsd.exe von Visual Studio. Xsd2Code ++ kann für die Verwendung von Listen oder Arrays angepasst werden und unterstützt große Schemas mit vielen Importanweisungen.

Hinweis auf einige Funktionen,

  • Generiert Geschäftsobjekte aus dem XSD-Schema oder der XML-Datei in flexiblen C # - oder Visual Basic-Code.
  • Support Framework 2.0 bis 4.x.
  • Unterstützt eine stark typisierte Sammlung (List, ObservableCollection, MyCustomCollection).
  • Unterstützt automatische Eigenschaften.
  • Generieren Sie XML-Lese- und Schreibmethoden (Serialisierung / Deserialisierung).
  • Datenbindungsunterstützung (WPF, Xamarin).
  • WCF (DataMember-Attribut).
  • Unterstützung für XML-Codierung (UTF-8/32, ASCII, Unicode, Benutzerdefiniert).
  • Camel Case / Pascal Case Unterstützung.
  • Einschränkungsunterstützung ([StringLengthAttribute = true / false], [RegularExpressionAttribute = true / false], [RangeAttribute = true / false]).
  • Unterstützt große und komplexe XSD-Dateien.
  • Unterstützung von DotNet Core & Standard
Haas Franck
quelle
0

Ich weiß, dass diese Frage alt ist, aber ich bin darauf gestoßen und habe eine andere Antwort als alle anderen :-)

Der übliche Weg (wie in den obigen Kommentaren erwähnt) besteht darin, eine Klasse zu generieren und Ihre XML-Datei zu de-serialisieren.

Aber ( Warnung: schamlose Eigenwerbung hier ) ich nur ein nuget Paket veröffentlicht, hier , mit denen Sie nicht zu. Du gehst einfach:

string xml = System.IO.File.ReadAllText(@"C:\test\books.xml");
var book = Dandraka.XmlUtilities.XmlSlurper.ParseText(xml);

Das ist es buchstäblich, nichts anderes benötigt. Und vor allem, wenn sich Ihre XML-Datei ändert, ändert sich auch Ihr Objekt automatisch.

Wenn Sie es vorziehen , die DLL direkt zum Download, ist die Github Seite hier .

Jim Andrakakis
quelle
-7
public string Serialize<T>(T settings)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    StringWriter outStream = new StringWriter();
    serializer.Serialize(outStream, settings);
    return outStream.ToString();
}
Mandoleen
quelle
5
Dies ist das Serialisieren und nicht das Deserialisieren.
Alexc95
1
Sie haben gerade hier Code geschrieben. Ohne Erklärung ist es für viele bedeutungslos.
M. Haché
Code entsorgt keine Streams
Bigfoot