将XML字符串转换为对象


179

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

消息的形式为:

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

我是.Net的新手,不确定执行此操作的最佳实践。我以前使用过Java的JAXB,但不确定是否存在类似的东西,或者是否会以其他方式处理。


3
您是否有这些成为对象,或者是否要动态生成对象?
斯蒂芬,2010年


对我来说,这是最好的选择:stackoverflow.com/a/24184283/2647430
Ivan Lopez

Answers:


276

您需要使用xsd.exeWindows SDK附带的工具,该工具类似于以下目录:

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

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

xsd yourfile.xml

这样yourfile.xsd,您可以在第二步中使用再次xsd.exe转换为C#类:

xsd yourfile.xsd /c

这应该给您一个文件yourfile.cs,其中包含一个C#类,您可以使用该类反序列化所获取的XML文件-类似于:

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

感谢您的详细解释。就我而言,XML是通过套接字传入的,并且是字符串。我将如何反序列化字符串而不是XML文件?
史蒂夫2010年

5
@Steve:您可以打开StringReader并传递Deserialize方法。StringReader派生自TextReader。
Skurmedel'7

您是否希望使用使用Linq提到的Fahad方法?
史蒂夫2010年

2
@Steve:是的,我会-反序列化为对象并能够戳探对象的属性似乎比对XML元素,属性,子节点等进行大量摆动要容易得多。Linq-to-XML很棒XML是不规则的,并且一直在变化,或者是事先未知的。
marc_s

7
这个网站比xsd工具IMO容易得多:xmltocsharp.azurewebsites.net
nasch 2016年

226

您有两种可能性。

方法1。XSD工具


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

  1. 打开“ 开发人员命令提示符”,
    您可以在中找到它;Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools 如果您使用Windows 8,也可以在“ 开始”屏幕中开始键入“ 开发人员命令提示符”
  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
    在此处输入图片说明

就是这样!

用法


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

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
干杯。重新:方法2,您必须以.net 4.5为目标,否则该选项不可用。
timB33

12
方法2非常有用!感谢那。我不知道存在。
Dominic Bindley '16

1
方法2的荣誉,就像魅力一样。尝试简单地以编程方式解析XML而不必实现无聊的类时,这非常有用。
Alex

1
首先应将“特殊粘贴”作为它的一种-这是最简单的方法。限制“ .Net Framework> = 4.5”在2017
Michael Freidgeim

2
“将XML作为类粘贴”需要安装Visual Studio的WCF工作负载。
Lennart

49

尝试使用此方法将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);

6
收到了这个错误xmlns =''>没想到。“},有什么想法吗?
Prashant 2014年

问题是,您需要提前完善班级。也许是在给定XML时输出类的函数?xsd.exe命中并错过(多数是复杂内容的错过)...
Yumi Koizumi

1
噢,天哪,我花了数小时来处理.nets xml序列化程序,而这一切都是可行的。
克里斯托弗·克拉克

11

只需以管理身份运行Visual Studio 2013 ...复制Xml文件的内容。.转到Visual Studio 2013>编辑>选择性粘贴>将Xml粘贴为C#类它将根据您的Xml文件内容创建c#类。


7

以防万一有人发现这有用:

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

5

您可以如上所述生成类,或手动编写它们:

[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
优秀的帖子!我根据文档github.com/wojtpl2/ExtendedXmlSerializer
user1477388 '18


2

简化达米安的好答案,

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

创建一个DTO作为CustomObject

使用以下方法使用JAXB将XML字符串转换为DTO

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消息的xsd,则可以使用.Net xsd.exe工具生成c#类。

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


0

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


0

使用高级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,自定义)。
  • 骆驼皮/帕斯卡皮套支持。
  • 限制支持([StringLengthAttribute = true / false],[RegularExpressionAttribute = true / false],[RangeAttribute = true / false])。
  • 支持大而复杂的XSD文件。
  • 支持DotNet Core和标准

0

我知道这个问题很旧,但是我偶然发现了这个问题,而且答案与其他所有人都不同:-)

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

但是,(警告:无耻的自我推销在这里)我刚刚出版了一NuGet包,在这里,有了它您就不必。你就去:

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

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

如果您想直接下载dll,请在github页面上找到


-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
这是序列化的方法,而不是反序列化的方法。
alexc95 '16

1
您只是在这里编写代码。没有解释,对许多人来说毫无意义。
M.Haché

代码不处理流
大脚怪(
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.