将 XML 字符串转换为对象

Convert XML String to Object

提问人:Steve 提问时间:7/6/2010 最后编辑:ΩmegaManSteve 更新时间:7/1/2022 访问量:486982

问:

我正在通过套接字接收 XML 字符串,并希望将它们转换为 C# 对象。

消息的格式如下:

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

这怎么能做到?

C# XML 解析 XML 序列化

评论

3赞 Stephan 7/6/2010
您是否有这些对象,或者您想动态生成对象?
0赞 Aykut Çevik 7/6/2010
查找此帖子: http://stackoverflow.com/questions/765422/jaxb-equivalent-in-c
0赞 Ivan Lopez 8/17/2017
对我来说,这是最好的选择:stackoverflow.com/a/24184283/2647430

答:

309赞 marc_s 7/6/2010 #1

您需要使用与 Windows SDK 一起安装到类似于以下内容的目录中的工具:xsd.exe

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

在 64 位计算机上:

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

在 Windows 10 计算机上:

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

在第一次运行时,使用示例 XML 并将其转换为 XSD 文件(XML 架构文件):xsd.exe

xsd yourfile.xml

这为您提供了 ,在第二步中,您可以再次将其转换为 C# 类:yourfile.xsdxsd.exe

xsd yourfile.xsd /c

这应该会给你一个文件,其中包含一个 C# 类,你可以用它来反序列化你得到的 XML 文件 - 类似于:yourfile.cs

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

在大多数情况下应该效果很好。

更新:XML 序列化程序将接受任何流作为其输入 - 文件或内存流都可以:

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

或使用 StringReader:

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

评论

0赞 Steve 7/6/2010
感谢您的详细解释。就我而言,XML 来自套接字,并且是一个字符串。如何反序列化字符串而不是 XML 文件?
5赞 Skurmedel 7/6/2010
@Steve:可以打开 StringReader 并传递 Deserialize 方法。StringReader 派生自 TextReader。
0赞 Steve 7/6/2010
你更喜欢你的方法而不是 Fahad 提到的使用 Linq 的方法吗?
2赞 marc_s 7/6/2010
@Steve:是的,我会 - 反序列化为对象并能够戳对象的属性似乎比对 XML 元素、属性、子节点等进行大量摆动要容易得多。如果 XML 不规则且一直在变化,或者事先不知道,则 Linq-to-XML 非常有用。
9赞 nasch 10/18/2016
这个网站比 XSD 工具 IMO 容易得多:xmltocsharp.azurewebsites.net
0赞 Amitabh 7/6/2010 #2

如果您有 xml 消息的 xsd,则可以使用 .Net xsd.exe 工具生成 c# 类。

然后,可以使用此 .Net 类来生成 xml。

3赞 DaveShaw 7/6/2010 #3

可以使用 xsd.exe 在 .Net 中创建架构绑定类,然后使用 XmlSerializer 反序列化字符串:http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.deserialize.aspx

57赞 RJ. 7/6/2010 #4

尝试此方法将 Xml 转换为对象。它正是为您正在做的事情而设计的:

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

使用以下代码调用它:

YourStrongTypedEntity entity = FromXml<YourStrongTypedEntity>(YourMsgString);

评论

7赞 Prashant 11/5/2014
收到此错误xmlns=''> was not expected.“},有什么想法吗?
0赞 Yumi Koizumi 6/4/2017
问题是,你需要提前让你的班级完美地形成。也许是一个在给定 XML 时输出类的函数?XSD,.exe 是命中和未命中(主要是复杂的东西)...
1赞 christopher clark 11/18/2017
哦,我的上帝,我花了几个小时处理 .nets xml 序列化程序,这从一开始就起作用了。
0赞 Alex Zel 11/24/2021
如果出现“出乎意料”错误,请使用上面的解决方案 编辑 -> 选择性粘贴,而不是手动创建类
0赞 Skurmedel #5

除了此处的其他答案之外,您自然可以使用 XmlDocument 类(用于类似 XML DOM 的读取)或 XmlReader(仅快进读取器)来“手动”完成此操作。

-8赞 Mandoleen 11/14/2011 #6
public string Serialize<T>(T settings)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    StringWriter outStream = new StringWriter();
    serializer.Serialize(outStream, settings);
    return outStream.ToString();
}

评论

5赞 Alex 4/22/2016
这是序列化的方式,而不是反序列化的方式。
1赞 M. Haché 7/22/2016
你刚刚在这里写了代码。没有解释,这对许多人来说毫无意义。
0赞 bigfoot 2/8/2019
代码不处理流
272赞 Damian Drygiel 10/27/2013 #7

你有两种可能性。

方法 1.XSD 工具


假设您的 XML 文件位于此位置C:\path\to\xml\file.xml

  1. 打开开发人员命令提示符,
    您可以在以下位置找到它 或者,如果您有Windows 8,则可以在“开始”屏幕中开始键入开发人员命令提示
    Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools
  2. 通过键入更改 XML 文件目录的位置cd /D "C:\path\to\xml"
  3. 通过键入 xml 文件创建 XSD 文件xsd file.xml
  4. 通过键入创建 C# 类xsd /c file.xsd

就是这样!您已从 xml 文件中生成了 C# 类C:\path\to\xml\file.cs

方法 2 - 特殊粘贴


必需的 Visual Studio 2012+,其中 .Net Framework >= 4.5 作为项目目标,并安装了“Windows Communication Foundation”单个组件

  1. 将 XML 文件的内容复制到剪贴板
  2. 将新的空类文件 (Shift+Alt+C)
  3. 打开该文件,然后在菜单中单击Edit > Paste special > Paste XML As Classes
    enter image description here

就是这样!

用法


这个帮助程序类的用法非常简单:

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

您现在要做的就是:

    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赞 timB33 12/12/2013
干杯。回复:方法 2,您必须以 .NET 4.5 为目标,否则该选项不可用。
18赞 Dominic Bindley 2/13/2016
方法 2 非常有用!谢谢你。我不知道它的存在。
1赞 Alex 11/3/2016
对方法 2 的赞誉,就像一个魅力。当尝试以编程方式简单地解析 XML 而不必实现无聊的类时,这非常有用。
1赞 Michael Freidgeim 12/31/2016
您应该将“Paste Special”作为第一种方法 - 这是最简单的方法。限制“.Net Framework >= 4.5”在 2017 年并不重要。
2赞 Lennart 11/23/2017
“将 XML 粘贴为类”需要安装 Visual Studio 的 WCF 工作负载。
13赞 user2667652 6/12/2014 #8

只需将 Visual Studio 2013 作为管理运行... 复制 Xml 文件的内容。 转到 Visual Studio 2013 >编辑>粘贴特殊>将 xml 粘贴为 C# 类 它将根据您的 Xml 文件内容创建您的 c# 类。

11赞 Rasmus-E 2/2/2017 #9

以防万一有人可能会觉得这很有用:

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

您可以使用以下命令来调用它:

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

评论

1赞 Tim Maes 6/30/2022
XmlConvert.SerializeObject(myObject) :)缺少分号
1赞 Rasmus-E 7/1/2022
@TimMaes 谢谢!刚刚更新了片段!(1975 天后) ;-)
0赞 Tim Maes 7/4/2022
不能再等一天了:)
9赞 Wojciech Nagórski 2/16/2017 #10

您可以按上述方式生成类,也可以手动编写:

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

然后,可以使用 ExtendedXmlSerializer 进行序列化和反序列化。

分期付款可以从 nuget 安装 ExtendedXmlSerializer 或运行以下命令:

Install-Package ExtendedXmlSerializer

序列化:

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

反序列化

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

此序列化程序支持:

  • 从标准 XMLSerializer 反序列化 xml
  • 序列化类、结构、泛型类、基元类型、泛型列表和字典、数组、枚举
  • 具有属性接口的序列化类
  • 序列化循环引用和引用 ID
  • 旧版本 xml 的反序列化
  • 属性加密
  • 自定义序列化程序
  • 支持 XmlElementAttribute 和 XmlRootAttribute
  • POCO - 所有配置(迁移、自定义序列化程序等)都在类之外

ExtendedXmlSerializer 支持 .NET 4.5 或更高版本和 .NET Core。可以将其与 WebApi 和 AspCore 集成。

评论

1赞 user1477388 7/21/2018
优秀的帖子!我更新了代码以根据文档 github.com/wojtpl2/ExtendedXmlSerializer 对其进行现代化改造
3赞 Sam Jazz 8/8/2018 #11

简化达米安的精彩回答,

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);
    }
}
0赞 Haas Franck 2/27/2019 #12

另一种使用高级 xsd 到 c# 类生成工具的方法:xsd2code.com。这个工具非常方便和强大。它比 Visual Studio 中的 xsd.exe 工具具有更多的自定义功能。Xsd2Code++ 可以自定义为使用列表或数组,并支持具有大量 Import 语句的大型架构。

注意一些功能,

  • 将业务对象从 XSD 架构或 XML 文件生成为灵活的 C# 或 Visual Basic 代码。
  • 支持框架 2.0 到 4.x
  • 支持强类型集合(List、ObservableCollection、MyCustomCollection)。
  • 支持自动属性。
  • 生成 XML 读取和写入方法(序列化/反序列化)。
  • 数据绑定支持(WPF、Xamarin)。
  • WCF(DataMember 属性)。
  • XML 编码支持(UTF-8/32、ASCII、Unicode、自定义)。
  • 骆驼箱/Pascal 箱子支持。
  • 限制支持 ([StringLengthAttribute=true/false], [RegularExpressionAttribute=true/false], [RangeAttribute=true/false])。
  • 支持大型和复杂的XSD文件。
  • 支持 DotNet Core 和标准
2赞 Jim Andrakakis 8/23/2019 #13

我知道这个问题很老了,但我偶然发现了它,我的答案与其他人不同:-)

通常的方法(正如上面的评论者所提到的)是生成一个类并反序列化你的 xml。

但是(警告:这里是无耻的自我推销)我刚刚在这里发布了一个 nuget 包,您不必使用它。你只需去:

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

从字面上看就是这样,不需要其他任何东西。而且,最重要的是,如果你的 xml 发生了变化,你的对象也会自动改变。

如果您更喜欢直接下载 dll,github 页面在这里。

1赞 Mohit Singh 12/29/2019 #14

将 DTO 创建为 CustomObject

使用以下方法将 XML 字符串转换为 DTO 使用 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;
}
3赞 Olumide 7/24/2020 #15

截至目前(2020-07-24),我已经浏览了所有答案,并且必须有一个更简单,更熟悉的方法来解决这个问题,如下所示。

两种情况...一种是如果 XML 字符串格式正确,即它以 like 或 its likes 开头,然后遇到问题中的根元素。另一个是如果它的格式不正确,即只是根元素(例如 在问题中)及其子节点。<?xml version="1.0" encoding="utf-16"?><msg><msg>

首先,它只是一个简单的类,它包含与 XML 中根节点的子节点匹配的属性,这些属性在不区分大小写的名称中。所以,从问题来看,它会是这样的......

public class TheModel
{
    public int Id { get; set; }
    public string Action { get; set; }
}

以下是代码的其余部分...

// These are the key using statements to add.
using Newtonsoft.Json;
using System.Xml;

bool isWellFormed = false;
string xml =  = @"
<msg>
   <id>1</id>
   <action>stop</action>
</msg>
";

var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
if (isWellFormed)
{
    xmlDocument.RemoveChild(xmlDocument.FirstChild); 
    /* i.e. removing the first node, which is the declaration part. 
    Also, if there are other unwanted parts in the XML, 
    write another similar code to locate the nodes 
    and remove them to only leave the desired root node 
    (and its child nodes).*/
}

var serializedXmlNode = JsonConvert.SerializeXmlNode(
            xmlDocument, 
            Newtonsoft.Json.Formatting.Indented, 
            true
            );
var theDesiredObject = JsonConvert.DeserializeObject<TheModel>(serializedXmlNode);