Chuyển đổi chuỗi XML thành đối tượng


179

Tôi đang nhận được các chuỗi XML qua một ổ cắm và muốn chuyển đổi các chuỗi này thành các đối tượng C #.

Các tin nhắn có dạng:

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

Tôi chưa quen với .Net và không chắc chắn cách thực hành tốt nhất để thực hiện việc này. Tôi đã sử dụng JAXB cho Java trước đây và không chắc chắn liệu có thứ gì tương tự hay không, nếu điều này sẽ được xử lý theo một cách khác.


3
Bạn có các đối tượng này trở thành hoặc bạn muốn tự động tạo các đối tượng?
Stephan


Đối với tôi đây là lựa chọn tốt nhất: stackoverflow.com/a/24184283/2647430
Ivan Lopez

Câu trả lời:


277

Bạn cần sử dụng xsd.execông cụ được cài đặt với SDK Windows vào một thư mục tương tự như:

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

Và trên máy tính 64 bit:

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

Và trên máy tính Windows 10:

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

Trong lần chạy đầu tiên, bạn sử dụng xsd.exevà bạn chuyển đổi XML mẫu của mình thành tệp XSD (tệp lược đồ XML):

xsd yourfile.xml

Điều này mang lại cho bạn yourfile.xsd, trong bước thứ hai, bạn có thể chuyển đổi lại bằng cách sử dụng xsd.exethành lớp C #:

xsd yourfile.xsd /c

Điều này sẽ cung cấp cho bạn một tệp yourfile.cssẽ chứa một lớp C # mà bạn có thể sử dụng để giải tuần tự hóa tệp XML mà bạn nhận được - đại loại như:

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

Nên làm việc khá tốt cho hầu hết các trường hợp.

Cập nhật: trình tuần tự hóa XML sẽ lấy bất kỳ luồng nào làm đầu vào của nó - một tệp hoặc một luồng bộ nhớ sẽ ổn:

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

hoặc sử dụng StringReader:

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

Cảm ơn vì lời giải thích chi tiết. Trong trường hợp của tôi, XML xuất hiện trên một ổ cắm và là một chuỗi. Làm cách nào để tôi hủy tuần tự hóa một chuỗi thay vì tệp XML?
Steve

5
@Steve: Bạn có thể mở StringReader và truyền phương thức Deserialize. StringReader có nguồn gốc từ TextReader.
Skurmedel

Bạn có muốn cách tiếp cận của bạn với một Fahad được đề cập bằng cách sử dụng Linq?
Steve

2
Tài khoản XML không thường xuyên và thay đổi mọi lúc, hoặc không biết trước thời hạn.
marc_s

7
Trang web này dễ dàng hơn nhiều so với công cụ xsd IMO: xmltocsharp.azurewebsites.net
vào

226

Bạn có hai khả năng.

Phương pháp 1. Công cụ XSD


Giả sử rằng bạn có tệp XML của mình ở vị trí này C:\path\to\xml\file.xml

  1. Mở dấu nhắc lệnh nhà phát triển
    Bạn có thể tìm thấy nó trong Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools Hoặc nếu bạn có Windows 8, bạn chỉ cần bắt đầu nhập Dấu nhắc lệnh của nhà phát triển trong màn hình Bắt đầu
  2. Thay đổi vị trí vào thư mục tệp XML của bạn bằng cách nhập cd /D "C:\path\to\xml"
  3. Tạo tệp XSD từ tệp xml của bạn bằng cách nhậpxsd file.xml
  4. Tạo các lớp C # bằng cách gõxsd /c file.xsd

Và đó là nó! Bạn đã tạo các lớp C # từ tệp xml trongC:\path\to\xml\file.cs

Phương pháp 2 - Dán đặc biệt


Bắt buộc Visual Studio 2012+ với .Net Framework> = 4.5 làm mục tiêu dự án và thành phần riêng lẻ 'Windows Communication Foundation' được cài đặt

  1. Sao chép nội dung tệp XML của bạn vào khay nhớ tạm
  2. Thêm vào giải pháp của bạn tập tin lớp mới, trống ( Shift+ Alt+ C)
  3. Mở tập tin đó và trong menu bấm vào Edit > Paste special > Paste XML As Classes
    nhập mô tả hình ảnh ở đây

Và đó là nó!

Sử dụng


Cách sử dụng rất đơn giản với lớp người trợ giúp này:

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

Tất cả bạn phải làm bây giờ, là:

    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
chúc mừng re: phương thức 2, bạn phải nhắm mục tiêu .net 4.5 nếu không thì tùy chọn không khả dụng.
timB33

12
Phương pháp 2 rất hữu ích! Cảm ơn vì điều đó. Tôi không có ý tưởng rằng đã tồn tại.
Đaminh Bindley

1
Kudos cho phương pháp 2, hoạt động như một lá bùa. Tuyệt vời khi cố gắng phân tích cú pháp một cách lập trình XML mà không phải thực hiện các lớp nhàm chán.
Alex

1
Bạn nên tạo "Dán đặc biệt" làm phương pháp đầu tiên - đó là phương pháp đơn giản nhất. Giới hạn ".Net Framework> = 4.5" không quan trọng trong năm 2017.
Michael Freidgeim

2
"Dán XML dưới dạng các lớp" yêu cầu khối lượng công việc WCF cho Visual Studio được cài đặt.
Lennart

49

Hãy thử phương pháp này để chuyển đổi Xml thành một đối tượng. Nó được làm cho chính xác những gì bạn đang làm:

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

Gọi nó bằng mã này:

YourStrongTypedEntity entity = FromXml<YourStrongTypedEntity>(YourMsgString);

6
Có lỗi này xmlns = ''> không được mong đợi. "}, Có ý kiến ​​gì không?
Prashant

Vấn đề là, bạn cần phải có lớp của bạn được hình thành hoàn hảo trước. Có lẽ một hàm tạo ra một lớp khi được cung cấp XML? xsd.exe là hit & miss (chủ yếu là bỏ lỡ những thứ phức tạp) ...
Yumi Koizumi

1
Ôi chúa ơi, tôi đã dành hàng giờ để xử lý .nets xml serializer, và điều này đã hoạt động ngay ngoài cổng.
christopher clark

11

Đơn giản chỉ cần chạy Visual Studio 2013 của bạn dưới dạng Quản trị ... Sao chép nội dung của tệp Xml của bạn .. Truy cập Visual Studio 2013> Chỉnh sửa> Dán đặc biệt> Dán Xml dưới dạng các lớp C # Nó sẽ tạo các lớp c # của bạn theo nội dung tệp Xml của bạn.


7

Chỉ trong trường hợp bất cứ ai cũng có thể tìm thấy điều này hữu ích:

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

Bạn có thể gọi nó bằng cách sử dụng:

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

5

Bạn có thể tạo lớp như được mô tả ở trên hoặc viết chúng theo cách thủ công:

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

Sau đó, bạn có thể sử dụng ExtendedXmlSerializer để tuần tự hóa và giải tuần tự hóa.

Instalation Bạn có thể cài đặt ExtendedXmlSerializer từ nuget hoặc chạy lệnh sau:

Install-Package ExtendedXmlSerializer

Tuần tự hóa:

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

Khử muối

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

Hỗ trợ nối tiếp này:

  • Giải nén xml từ XMLSerializer tiêu chuẩn
  • Lớp tuần tự hóa, struct, lớp chung, kiểu nguyên thủy, danh sách chung và từ điển, mảng, enum
  • Lớp tuần tự hóa với giao diện thuộc tính
  • Id tham chiếu tuần tự và tham chiếu Id
  • Giải trừ phiên bản cũ của xml
  • Mã hóa tài sản
  • Tuần tự tùy chỉnh
  • Hỗ trợ XmlEuityAttribution và XmlRootAttribution
  • POCO - tất cả các cấu hình (di chuyển, tuần tự hóa tùy chỉnh ...) nằm ngoài lớp

ExtendedXmlSerializer hỗ trợ .NET 4.5 trở lên và .NET Core . Bạn có thể tích hợp nó với WebApi và AspCore.


1
Bài đăng tuyệt vời! Tôi đã cập nhật mã để hiện đại hóa nó theo tài liệu github.com/wojtpl2/ExtendsXmlSerializer
user1477388 21/07/18

3

Bạn có thể sử dụng xsd.exe để tạo các lớp liên kết lược đồ trong .Net sau đó XmlSerializer để Deserialize chuỗi: http://msdn.microsoft.com/en-us/l Library / system.xml.serialization.xmlserializer.deserialize.aspx


2

Đơn giản hóa câu trả lời tuyệt vời của 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);
    }
}

1

Tạo DTO dưới dạng CustomObject

Sử dụng phương pháp bên dưới để chuyển đổi Chuỗi XML thành DTO bằng 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;
}

0

Nếu bạn có xsd của thông báo xml thì bạn có thể tạo các lớp c # bằng cách sử dụng công cụ .Net xsd.exe.

Lớp .Net này sau đó có thể được sử dụng để tạo xml.


0

Ngoài các câu trả lời khác ở đây, bạn có thể sử dụng lớp XmlDocument một cách tự nhiên , để đọc giống như XML DOM hoặc XmlReader , trình đọc chỉ chuyển tiếp nhanh, để thực hiện "bằng tay".


0

Một cách khác với Công cụ tạo các lớp từ xsd đến c # Nâng cao: xsd2code.com. Công cụ này rất tiện dụng và mạnh mẽ. Nó có nhiều tùy chỉnh hơn công cụ xsd.exe từ Visual Studio. Xsd2Code ++ có thể được tùy chỉnh để sử dụng Danh sách hoặc Mảng và hỗ trợ các lược đồ lớn với nhiều câu lệnh Nhập.

Lưu ý một số tính năng,

  • Tạo các đối tượng kinh doanh từ XSD Schema hoặc tệp XML thành mã C # hoặc Visual Basic linh hoạt.
  • Hỗ trợ Khung 2.0 đến 4.x
  • Hỗ trợ bộ sưu tập đánh máy mạnh (Danh sách, ObservableCollection, MyCustomCollection).
  • Hỗ trợ tính chất tự động.
  • Tạo các phương thức đọc và ghi XML (tuần tự hóa / giải tuần tự hóa).
  • Hỗ trợ dữ liệu (WPF, Xamarin).
  • WCF (thuộc tính DataMember).
  • Hỗ trợ mã hóa XML (UTF-8/32, ASCII, Unicode, Tùy chỉnh).
  • Vỏ lạc đà / Ốp lưng Pascal.
  • hỗ trợ hạn chế ([StringLạngAttribution = true / false], [RoutExpressionAttribution = true / false], [RangeAttribution = true / false]).
  • Hỗ trợ tệp XSD lớn và phức tạp.
  • Hỗ trợ tiêu chuẩn & lõi DotNet

0

Tôi biết câu hỏi này đã cũ, nhưng tôi vấp vào nó và tôi có một câu trả lời khác hơn, tốt hơn, mọi người khác :-)

Cách thông thường (như các nhà bình luận ở trên đã đề cập) là tạo một lớp và hủy xê-ri hóa xml của bạn.

Nhưng ( cảnh báo: tự quảng cáo không biết xấu hổ ở đây ) Tôi vừa xuất bản một gói nuget, ở đây , mà bạn không phải làm. Bạn chỉ cần đi:

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

Đó là nghĩa đen của nó, không có gì khác cần thiết. Và, quan trọng nhất, nếu xml của bạn thay đổi, đối tượng của bạn cũng thay đổi tự động.

Nếu bạn muốn tải xuống dll trực tiếp, trang github ở đây .


-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
Đây là cách để tuần tự hóa, không phải làm thế nào để giải tuần tự hóa.
alexc95

1
Bạn chỉ cần viết mã ở đây. Không có lời giải thích, nó là vô nghĩa đối với nhiều người.
M. Haché

Mã không loại bỏ các luồng
bigfoot
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.