Konversi XML String ke Object

179

Saya menerima string XML melalui soket, dan ingin mengubahnya menjadi objek C #.

Pesannya berupa:

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

Saya baru mengenal .Net, dan tidak yakin praktik terbaik untuk melakukan ini. Saya telah menggunakan JAXB untuk Java sebelumnya, dan tidak yakin apakah ada sesuatu yang serupa, atau apakah ini akan ditangani dengan cara yang berbeda.

Steve
sumber
3
Apakah Anda memiliki objek ini menjadi atau Anda ingin secara dinamis menghasilkan objek?
Stephan
Bagi saya ini adalah pilihan terbaik: stackoverflow.com/a/24184283/2647430
Ivan Lopez

Jawaban:

277

Anda perlu menggunakan xsd.exealat yang terinstal dengan Windows SDK ke direktori yang mirip dengan:

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

Dan pada komputer 64-bit:

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

Dan pada komputer Windows 10:

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

Pada percobaan pertama, Anda menggunakan xsd.exedan Anda mengonversi sampel XML Anda menjadi file XSD (file skema XML):

xsd yourfile.xml

Ini memberi Anda yourfile.xsd, yang pada langkah kedua, Anda dapat mengkonversi lagi menggunakan xsd.exekelas C #:

xsd yourfile.xsd /c

Ini akan memberi Anda file yourfile.csyang akan berisi kelas C # yang dapat Anda gunakan untuk menghapus deserialisasi file XML yang Anda peroleh - sesuatu seperti:

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

Harus bekerja dengan cukup baik untuk sebagian besar kasus.

Pembaruan: serializer XML akan mengambil aliran apa pun sebagai input - baik file atau aliran memori akan baik-baik saja:

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

atau gunakan StringReader:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
StringReader rdr = new StringReader(inputString);
msg resultingMessage = (msg)serializer.Deserialize(rdr);
marc_s
sumber
Terima kasih untuk penjelasan rinci. Dalam kasus saya, XML datang melalui soket, dan merupakan string. Bagaimana saya menghapus serialisasi string alih-alih file XML?
Steve
5
@Steve: Anda bisa membuka StringReader dan meneruskan metode Deserialize. StringReader berasal dari TextReader.
Skurmedel
Apakah Anda lebih suka pendekatan Anda ke salah satu yang disebutkan Fahad menggunakan Linq?
Steve
2
@Steve: ya, saya akan - deserializing menjadi objek dan mampu menyodok properti objek tampaknya jauh lebih mudah daripada melakukan banyak gerak-gerik dengan elemen XML, atribut, node anak dll. Linq-to-XML sangat bagus jika XML tidak teratur dan berubah sepanjang waktu, atau tidak diketahui sebelumnya.
marc_s
7
Situs web ini jauh lebih mudah daripada alat xsd IMO: xmltocsharp.azurewebsites.net
nasch
226

Anda memiliki dua kemungkinan.

Metode 1. Alat XSD


Misalkan Anda memiliki file XML di lokasi ini C:\path\to\xml\file.xml

  1. Buka Prompt Perintah Pengembang
    Anda dapat menemukannya di Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Atau jika Anda memiliki Windows 8 dapat mulai mengetik Prompt Perintah Pengembang di layar Mulai
  2. Ubah lokasi ke direktori file XML Anda dengan mengetik cd /D "C:\path\to\xml"
  3. Buat file XSD dari file xml Anda dengan mengetikxsd file.xml
  4. Buat kelas C # dengan mengetikxsd /c file.xsd

Dan itu dia! Anda telah menghasilkan kelas C # dari file xml diC:\path\to\xml\file.cs

Metode 2 - Tempel khusus


Diperlukan Visual Studio 2012+ dengan .Net Framework> = 4.5 sebagai target proyek dan komponen individual 'Windows Communication Foundation' diinstal

  1. Salin konten file XML Anda ke clipboard
  2. Tambahkan ke solusi Anda, file kelas kosong baru ( Shift+ Alt+ C)
  3. Buka file itu dan klik menu Edit > Paste special > Paste XML As Classes
    masukkan deskripsi gambar di sini

Dan itu dia!

Pemakaian


Penggunaan sangat sederhana dengan kelas pembantu ini:

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

Yang harus Anda lakukan sekarang adalah:

    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
sumber
7
Bersulang. re: metode 2, Anda harus menargetkan .net 4.5 lain pilihan tidak tersedia.
timB33
12
Metode 2 sangat berguna! Terima kasih untuk itu. Saya tidak tahu itu ada.
Dominic Bindley
1
Kudos untuk metode 2, bekerja seperti pesona. Hebat ketika mencoba untuk menguraikan XML secara terprogram tanpa harus mengimplementasikan kelas yang membosankan.
Alex
1
Anda harus menjadikan "Tempel Spesial" sebagai metode pertama - metode yang paling sederhana. Batasan ".Net Framework> = 4.5" tidak penting di 2017.
Michael Freidgeim
2
"Tempel XML sebagai kelas" memerlukan beban kerja WCF untuk Visual Studio yang diinstal.
Lennart
49

Coba metode ini untuk Mengonversi Xml ke objek. Itu dibuat untuk apa yang Anda lakukan:

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

Sebut saja menggunakan kode ini:

YourStrongTypedEntity entity = FromXml<YourStrongTypedEntity>(YourMsgString);
RJ.
sumber
6
Mendapat kesalahan ini xmlns = ''> tidak diharapkan. "}, Ada ide?
Prashant
Masalahnya adalah, Anda harus memiliki kelas Anda terbentuk sempurna di muka. Mungkin fungsi yang menghasilkan kelas saat diberi XML? xsd.exe terkena & rindu (kebanyakan ketinggalan untuk hal-hal kompleks) ...
Yumi Koizumi
1
Ya Tuhan, saya menghabiskan berjam-jam berurusan dengan .nets xml serializer, dan ini berhasil keluar dari gerbang.
christopher clark
11

Cukup Jalankan Visual Studio 2013 Anda sebagai Administrasi ... Salin konten file Xml Anda .. Buka Visual Studio 2013> Edit> Tempel Spesial> Tempel Xml sebagai Kelas C # Ini akan membuat kelas c # Anda sesuai dengan konten file Xml Anda.

pengguna2667652
sumber
7

Untuk berjaga-jaga kalau ada yang mungkin menemukan ini berguna:

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

Anda dapat menyebutnya menggunakan:

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

Anda dapat membuat kelas seperti yang dijelaskan di atas, atau menulisnya secara manual:

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

Kemudian Anda dapat menggunakan ExtendedXmlSerializer untuk membuat serial dan deserialize.

Instalasi Anda dapat menginstal ExtendedXmlSerializer dari nuget atau menjalankan perintah berikut:

Install-Package ExtendedXmlSerializer

Serialisasi:

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

Deserialisasi

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

Dukungan serializer ini:

  • Deserialization xml dari XMLSerializer standar
  • Kelas serialisasi, struct, kelas generik, tipe primitif, daftar generik dan kamus, array, enum
  • Kelas serialisasi dengan antarmuka properti
  • Referensi melingkar serialisasi dan nomor referensi
  • Deserialisasi versi lama xml
  • Enkripsi properti
  • Serializer khusus
  • Mendukung XmlElementAttribute dan XmlRootAttribute
  • POCO - semua konfigurasi (migrasi, serializer khusus ...) berada di luar kelas

ExtendedXmlSerializer mendukung .NET 4.5 atau lebih tinggi dan .NET Core . Anda dapat mengintegrasikannya dengan WebApi dan AspCore.

Wojtpl2
sumber
1
Pos luar biasa! Saya memperbarui kode untuk memodernisasi sesuai dengan dokumentasi github.com/wojtpl2/ExtendedXmlSerializer
user1477388
2

Menyederhanakan jawaban hebat Damian,

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

Buat DTO sebagai CustomObject

Gunakan metode di bawah ini untuk mengonversi String XML ke DTO menggunakan JAXB

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
sumber
0

Jika Anda memiliki xsd dari pesan xml maka Anda dapat membuat kelas c # menggunakan alat .Net xsd.exe.

Kelas .Net ini kemudian dapat digunakan untuk menghasilkan xml.

Amitabh
sumber
0

Selain jawaban lain di sini, Anda secara alami dapat menggunakan kelas XmlDocument , untuk membaca XML DOM, atau XmlReader , pembaca hanya-maju cepat, untuk melakukannya "dengan tangan".

Skurmedel
sumber
0

Cara lain dengan Advanced Generasi xsd ke c # kelas: xsd2code.com. Alat ini sangat berguna dan kuat. Ini memiliki lebih banyak penyesuaian daripada alat xsd.exe dari Visual Studio. Xsd2Code ++ dapat dikustomisasi untuk menggunakan Daftar atau Array dan mendukung skema besar dengan banyak pernyataan Impor.

Catatan beberapa fitur,

  • Menghasilkan objek bisnis dari Skema XSD atau file XML ke kode C # atau Visual Basic yang fleksibel.
  • Kerangka Dukungan 2.0 hingga 4.x
  • Mendukung koleksi yang diketik dengan kuat (Daftar, ObservableCollection, MyCustomCollection).
  • Mendukung properti otomatis.
  • Hasilkan metode membaca dan menulis XML (serialisasi / deserialisasi).
  • Dukungan penyatuan data (WPF, Xamarin).
  • WCF (atribut DataMember).
  • Dukungan Pengkodean XML (UTF-8/32, ASCII, Unicode, Custom).
  • Kasing unta / Pascal Case support.
  • dukungan pembatasan ([StringLengthAttribute = true / false], [RegularExpressionAttribute = true / false], [RangeAttribute = true / false]).
  • Mendukung file XSD yang besar dan kompleks.
  • Dukungan DotNet Core & standar
Haas Franck
sumber
0

Saya tahu pertanyaan ini sudah lama, tetapi saya tersandung ke dalamnya dan saya memiliki jawaban yang berbeda dari, well, orang lain :-)

Cara yang biasa (seperti yang disebutkan oleh komentator di atas) adalah membuat kelas dan menghapus serial xml Anda.

Tapi ( peringatan: promosi diri yang tak tahu malu di sini ) saya baru saja menerbitkan paket nuget, di sini Anda tidak perlu melakukannya. Anda hanya pergi:

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

Itu benar-benar itu, tidak ada yang dibutuhkan. Dan, yang paling penting, jika xml Anda berubah, objek Anda juga berubah secara otomatis.

Jika Anda lebih suka mengunduh dll secara langsung, halaman github ada di sini .

Jim Andrakakis
sumber
-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
sumber
5
Ini adalah bagaimana membuat cerita bersambung, bukan bagaimana melakukan deserialisasi.
alexc95
1
Anda baru saja menulis kode di sini. Tanpa penjelasan, tidak ada artinya bagi banyak orang.
M. Haché
Kode tidak membuang aliran
bigfoot