【问题标题】:Convert XML String to Object将 XML 字符串转换为对象
【发布时间】:2011-03-12 08:59:32
【问题描述】:

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

消息的格式为:

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

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

【问题讨论】:

标签: c# xml xml-parsing xml-serialization


【解决方案1】:

您需要使用xsd.exe 工具,该工具与 Windows 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 文件?
  • @Steve:您可以打开一个 StringReader 并传递 Deserialize 方法。 StringReader 派生自 TextReader。
  • 您是否更喜欢 Fahad 提到的使用 Linq 的方法?
  • @Steve:是的,我会 - 反序列化成一个对象并能够查看对象的属性似乎比对 XML 元素、属性、子节点等进行大量摆动要容易得多。Linq如果 XML 不规则且一直在变化,或者事先不知道,则 -to-XML 非常有用。
  • 这个网站比 xsd 工具 IMO 容易得多:xmltocsharp.azurewebsites.net
【解决方案2】:

你有两种可能。

方法一、XSD工具


假设您的 XML 文件位于此位置 C:\path\to\xml\file.xml
  1. 打开开发者命令提示符
    你可以在Start Menu &gt; Programs &gt; Microsoft Visual Studio 2012 &gt; Visual Studio Tools找到它 或者,如果您使用的是 Windows 8,则可以在 开始屏幕 中开始输入 Developer Command Prompt
  2. 通过键入cd /D "C:\path\to\xml" 将位置更改为您的 XML 文件目录
  3. 通过输入xsd file.xml,从您的xml文件创建XSD文件
  4. 通过键入 xsd /c file.xsd 创建 C# 类

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

方法 2 - 选择性粘贴


需要 Visual Studio 2012+ 和 .Net Framework >= 4.5 作为项目目标并安装“Windows Communication Foundation”单个组件
  1. 将 XML 文件的内容复制到剪贴板
  2. 向您的解决方案添加新的空类文件 (Shift+Alt+C)
  3. 打开该文件并在菜单中单击Edit &gt; Paste special &gt; 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>();

【讨论】:

  • 干杯。回复:方法 2,您必须以 .net 4.5 为目标,否则该选项不可用。
  • 方法2非常有用!感谢那。我不知道它存在。
  • 方法 2 的荣誉,就像一个魅力。非常适合尝试以编程方式简单地解析 XML 而不必实现无聊的类。
  • 您应该将“Paste Special”作为第一种方法——这是最简单的方法。限制“.Net Framework >= 4.5”在 2017 年并不重要。
  • “将 XML 粘贴为类”需要安装 Visual Studio 的 WCF 工作负载。
【解决方案3】:

试试这个方法将 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);

【讨论】:

  • 得到这个错误 xmlns=''> 不是预期的。"},有什么想法吗?
  • 问题是,你需要提前让你的班级完美地形成。也许是一个在给定 XML 时输出类的函数? xsd.exe 很受欢迎(主要是因为复杂的东西而错过)...
  • 天哪,我花了好几个小时来处理 .nets xml 序列化程序,结果一开始就奏效了。
  • 如果出现“未预料到”错误,请使用上面的解决方案编辑 -> 选择性粘贴,而不是手动创建类
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

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

      [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 集成。

      【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

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

          两种情况...一种是如果 XML 字符串是格式正确的,即它以 &lt;?xml version="1.0" encoding="utf-16"?&gt; 之类的东西开头,在遇到根之前元素,即问题中的&lt;msg&gt;。另一种是格式不正确,即只有根元素(例如问题中的&lt;msg&gt;)及其子节点。

          首先,只是一个简单的类,它包含与 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);
          

          【讨论】:

            【解决方案10】:

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

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

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

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

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

            如果你喜欢直接下载dll,github页面是here

            【讨论】:

              【解决方案11】:

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

              【讨论】:

                【解决方案12】:

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

                然后可以使用这个 .Net 类来生成 xml。

                【讨论】:

                  【解决方案13】:

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

                  【讨论】:

                    【解决方案14】:

                    使用高级 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 和标准

                    【讨论】:

                      【解决方案15】:
                      public string Serialize<T>(T settings)
                      {
                          XmlSerializer serializer = new XmlSerializer(typeof(T));
                          StringWriter outStream = new StringWriter();
                          serializer.Serialize(outStream, settings);
                          return outStream.ToString();
                      }
                      

                      【讨论】:

                      • 这是如何序列化,而不是如何反序列化。
                      • 你刚刚在这里写了代码。没有解释,对很多人来说毫无意义。
                      • 代码不处理流
                      猜你喜欢
                      • 2012-07-11
                      • 1970-01-01
                      • 2013-06-20
                      • 2018-11-27
                      • 2015-01-13
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多