XML Dizesini Nesneye Dönüştür


180

Bir soket üzerinden XML dizeleri alıyorum ve bu C # nesnelerine dönüştürmek istiyorum.

Mesajlar şu şekildedir:

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

.Net'te yeniyim ve bunu gerçekleştirmek için en iyi uygulamadan emin değilim. Daha önce Java için JAXB kullandım ve benzer bir şey olup olmadığından veya bunun farklı bir şekilde ele alındığından emin değildim.


3
Bunlar haline gelen nesneleriniz var mı veya nesneleri dinamik olarak oluşturmak mı istiyorsunuz?
Stephan


Benim için bu en iyi seçimdi: stackoverflow.com/a/24184283/2647430
Ivan Lopez

Yanıtlar:


277

Sen kullanmaya gerek xsd.exebenzer bir dizin içine bir şey, Windows SDK ile yüklü alır aracı:

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

64 bit bilgisayarlarda:

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

Windows 10 bilgisayarlarda:

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

İlk çalıştırmada kullanırsınız xsd.exeve örnek XML'nizi bir XSD dosyasına (XML şema dosyası) dönüştürürsünüz:

xsd yourfile.xml

Bu size yourfile.xsdikinci bir adımda tekrar kullanarak xsd.exebir C # sınıfına dönüştürebilmenizi sağlar :

xsd yourfile.xsd /c

Bu, aldığınız yourfile.csXML dosyasının serisini kaldırmak için kullanabileceğiniz bir C # sınıfı içeren bir dosya vermelidir - şöyle bir şey:

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

Çoğu durumda oldukça iyi çalışmalıdır.

Güncelleme: XML serileştiricisi herhangi bir akışı girişi olarak alacaktır - bir dosya veya bir bellek akışı iyi olacaktır:

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

veya bir StringReader kullanın:

XmlSerializer serializer = new XmlSerializer(typeof(msg));
StringReader rdr = new StringReader(inputString);
msg resultingMessage = (msg)serializer.Deserialize(rdr);

Detaylı açıklama için teşekkürler. Benim durumumda, XML bir soket üzerinden geliyor ve bir dizedir. XML dosyası yerine bir dizenin serisini nasıl serileştiririm?
Steve

5
@Steve: Bir StringReader açabilir ve Deserialize yöntemini iletebilirsiniz. StringReader, TextReader'dan türetilir.
Skurmedel

Linq kullanarak sözünü edilen Fahad'a yaklaşımınızı tercih eder misiniz?
Steve

2
@Steve: evet, bir nesneye serileştirmek ve nesnenin özelliklerine poke yapmak XML öğeleri, nitelikler, alt düğümler vb. İle çok fazla kıpır kıpır yapmaktan çok daha kolay görünüyor. XML düzensizdir ve her zaman değişir veya önceden bilinmez.
marc_s

7
Bu web sitesi xsd aracından çok daha kolay IMO: xmltocsharp.azurewebsites.net
nasch

227

İki ihtimaliniz var.

Yöntem 1. XSD aracı


XML dosyanızın bu konumda olduğunu varsayalım C:\path\to\xml\file.xml

  1. Açık Geliştirici Komut İstemi
    İçeri bulabilirsiniz Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools sadece yazmaya başlayabilirsiniz Windows 8 varsa Or Geliştirici Komut İstemi içinde Başlat ekranından
  2. XML dosya dizininizin konumunu yazarak değiştirin cd /D "C:\path\to\xml"
  3. Yazarak xml dosyanızdan XSD dosyası oluşturunxsd file.xml
  4. Yazarak C # sınıfları oluşturmaxsd /c file.xsd

Ve bu kadar! C # sınıflarını xml dosyasından oluşturdunuz.C:\path\to\xml\file.cs

Yöntem 2 - Özel yapıştır


.Net Framework> = 4.5 ile proje hedefi ve 'Windows Communication Foundation' bağımsız bileşeni yüklü olan Visual Studio 2012+

  1. XML dosyanızın içeriğini panoya kopyala
  2. Çözümünüze yeni, boş bir sınıf dosyası ekleyin ( Shift+ Alt+ C)
  3. Bu dosyayı açın ve menüde Edit > Paste special > Paste XML As Classes
    resim açıklamasını buraya girin

Ve bu kadar!

kullanım


Bu yardımcı sınıfla kullanımı çok basit:

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

Şimdi tek yapmanız gereken:

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

7
şerefe. re: yöntem 2, .net 4.5'i hedeflemeniz gerekir, aksi takdirde seçenek kullanılamaz.
timB33

12
Yöntem 2 gülünç yararlıdır! Bunun için teşekkürler. Bunun hakkında hiçbir fikrim yoktu.
Dominic Bindley

1
Yöntem 2 için Kudos, bir cazibe gibi çalışır. Sıkıcı sınıflar uygulamak zorunda kalmadan bir XML'yi programlı olarak ayrıştırmaya çalışırken harika.
Alex

1
İlk yöntem olarak "Özel Yapıştır" ı yapmalısınız - bu en basit yöntemdir. Sınırlama ".Net Framework> = 4.5" 2017'de önemli değil.
Michael Freidgeim

2
"XML'i sınıflar olarak yapıştır", yüklü Visual Studio için WCF iş yükünü gerektirir.
Lennart

50

Xml'yi bir nesneye dönüştürmek için bu yöntemi deneyin. Tam olarak ne yaptığınız için yapılır:

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

Bu kodu kullanarak arayın:

YourStrongTypedEntity entity = FromXml<YourStrongTypedEntity>(YourMsgString);

6
Bu hatayı aldınız xmlns = ''> beklenmiyordu. "}, Herhangi bir fikir?
Prashant

Sorun şu ki, sınıfınızı önceden mükemmel bir şekilde oluşturmalısınız. Belki XML verildiğinde bir sınıf çıkaran bir işlev olabilir? xsd.exe isabet ve özledim (çoğunlukla karmaşık şeyler için özledim) ...
Yumi Koizumi

1
Aman tanrım .nets xml serileştiricisiyle uğraşarak saatler geçirdim ve bu hemen kapıdan çıktı.
christopher clark

11

Visual Studio 2013'ünüzü Yönetim Olarak Çalıştırın ... Xml dosyanızın içeriğini kopyalayın .. Visual Studio 2013> Düzenle> Özel Yapıştır> Xml'yi C # Sınıfları olarak Yapıştır Xml dosya içeriğinize göre c # sınıflarınızı oluşturacaktır.


7

Herhangi birinin bunu yararlı bulması durumunda:

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

Aşağıdakileri kullanarak arayabilirsiniz:

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

5

Yukarıda açıklandığı gibi sınıf oluşturabilir veya elle yazabilirsiniz:

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

Ardından serileştirmek ve serisini kaldırmak için ExtendedXmlSerializer'ı kullanabilirsiniz .

Instalation ExtendedXmlSerializer'ı nuget'ten yükleyebilir veya aşağıdaki komutu çalıştırabilirsiniz:

Install-Package ExtendedXmlSerializer

Serile:

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

deserialization

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

Bu serileştirici şunları destekler:

  • Standart XMLSerializer'den seriyi kaldırma xml
  • Serileştirme sınıfı, yapı, genel sınıf, ilkel tür, genel liste ve sözlük, dizi, enum
  • Özellik arabirimli seri sınıf
  • Serileştirme dairesel referansı ve referans kimliği
  • XML'in eski sürümünün serileştirilmesi
  • Mülk şifreleme
  • Özel serileştirici
  • XmlElementAttribute ve XmlRootAttribute desteği
  • POCO - tüm yapılandırmalar (geçişler, özel serileştirici ...) sınıfın dışında

ExtendedXmlSerializer .NET 4.5 veya üstünü ve .NET Core'u destekler . WebApi ve AspCore ile entegre edebilirsiniz.


1
Mükemmel gönderi! Kodu modernize etmek için kodu github.com/wojtpl2/ExtendedXmlSerializer
user1477388 21:18


2

Damian'ın harika cevabını basitleştirmek,

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

1

CustomObject olarak bir DTO oluşturma

JAXB kullanarak XML Dizesi DTO dönüştürmek için aşağıdaki yöntemi kullanın

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

0

Xml iletisinin xsd'sine sahipseniz, .Net xsd.exe aracını kullanarak c # sınıfları oluşturabilirsiniz.

Bu .Net sınıfları daha sonra xml oluşturmak için kullanılabilir.


0

Buradaki diğer yanıtlara ek olarak, XML DOM benzeri okuma için doğal olarak XmlDocument sınıfını veya "elle" yapmak için hızlı ileri okuyuculu XmlReader'ı kullanabilirsiniz.


0

Gelişmiş bir xsd to c # sınıfları nesil Araçlar: xsd2code.com. Bu araç çok kullanışlı ve güçlü. Visual Studio'dan xsd.exe aracından çok daha fazla özelleştirme vardır. Xsd2Code ++ Listeler veya Diziler kullanmak için özelleştirilebilir ve birçok Import deyimiyle büyük şemaları destekler.

Bazı özelliklere dikkat edin,

  • İş nesnelerini XSD Şeması veya XML dosyasından esnek C # veya Visual Basic koduna oluşturur.
  • Destek Çerçevesi 2.0 ila 4.x
  • Güçlü yazılan koleksiyonu destekleyin (Liste, Gözlemlenebilir Toplama, MyCustomCollection).
  • Otomatik özellikleri destekler.
  • XML okuma ve yazma yöntemleri (serileştirme / serileştirme) oluşturun.
  • Veri desteği (WPF, Xamarin).
  • WCF (DataMember özniteliği).
  • XML Kodlama desteği (UTF-8/32, ASCII, Unicode, Özel).
  • Deve kılıfı / Pascal Kılıfı desteği.
  • kısıtlama desteği ([StringLengthAttribute = true / false], [RegularExpressionAttribute = true / false], [RangeAttribute = true / false]).
  • Büyük ve karmaşık XSD dosyasını destekleyin.
  • DotNet Core ve standart desteği

0

Bu sorunun eski olduğunu biliyorum, ama içine düştüm ve diğer herkesten farklı bir cevabım var :-)

Her zamanki yol (yukarıdaki yorumculardan bahsedildiği gibi) bir sınıf oluşturmak ve xml'nizin serileştirmesini sağlamaktır.

Ama ( uyarı: utanmaz öz tanıtım burada ) Sadece burada bir nuget paketi yayınladım, burada gerek yok. Siz sadece gidin:

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

Kelimenin tam anlamıyla bu, başka hiçbir şeye ihtiyaç yoktu. Ve en önemlisi, xml'niz değişirse, nesneniz de otomatik olarak değişir.

Doğrudan dll indirmeyi tercih ederseniz, github sayfası burada .


-7
public string Serialize<T>(T settings)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    StringWriter outStream = new StringWriter();
    serializer.Serialize(outStream, settings);
    return outStream.ToString();
}

5
Serileştirme nasıl yapılır, serileştirme değil.
alexc95

1
Buraya kod yazdınız. Hiçbir açıklama yapmadan, birçok kişi için anlamsızdır.
M. Haché

Kod akışları atmıyor
bigfoot
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.