反序列化具有不同标签的 XML 相同项目

Posted

技术标签:

【中文标题】反序列化具有不同标签的 XML 相同项目【英文标题】:Deserialize XML same items with different tag 【发布时间】:2021-11-30 01:43:49 【问题描述】:

这是一个我想反序列化并在桌面应用程序中使用的 XML 示例,用户可以在其中插入这样的 XML:

   <Settings>
        <FileName>C:\Users\myniceuser\Desktop\hello.xmldoc</FileName>
        <Zones>
                <Row1>
                        <Address>2</Address>strong text
                        <Zone>2</Zone>
                        <Installed>True</Installed>
                </Row1>
                <Row2>
                        <Address>3</Address>
                        <Zone>2</Zone>
                        <Installed>True</Installed>
                </Row2>
                <Row3>
                        <Address>4</Address>
                        <Zone>2</Zone>
                        <Installed>True</Installed>
                </Row3>
                <Row4>
                        <Address>5</Address>
                        <Zone>2</Zone>
                        <Installed>True</Installed>
                </Row4>
        </Zones>
        <Network_IP>010.000.008.072</Network_IP>
        <Ethernet_Enable>true</Ethernet_Enable>
        <Language>1</Language>
</Settings>

我实现的类是这个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace MyApp.Models

    [XmlRoot(ElementName = "Settings")]
    public class XML_Settings
    

        [XmlElement(ElementName = "FileName")]
        public string FileName  get; set; 


        //[XmlElement(ElementName = "Zones")]
        [XmlElement(ElementName ="Zones")]
        public Zones_Points[] Zones_Points  get; set; 

        [XmlElement(ElementName = "Network_IP")]
        public string NetworkIP  get; set; 

        [XmlElement(ElementName = "Ethernet_Enable")]
        public bool EthernetEnable  get; set; 

        [XmlElement(ElementName = "Language")]
        public int Language  get; set; 

    [XmlRoot(ElementName = "")]
    public partial class Zones_Points
    
        [XmlElement(ElementName ="Address")]
        public int Address  get; set; 

        [XmlElement(ElementName ="Zone")]
        public int PointZone  get; set; 

        [XmlElement(ElementName ="Installed")]
        public bool Installed  get; set; 



我这样反序列化:

Models.XML_Settings inputted_xml = new();
using StreamReader stream_xml = new StreamReader(xmlfile_path, CodePagesEncodingProvider.Instance.GetEncoding(1253));
                
XmlSerializer serializer = new XmlSerializer(typeof(Models.XML_Settings));

try

 Models.XML_Settings input = (Models.XML_GR6500)serializer.Deserialize(stream_xml);
 
 catch (Exception exception)
 
 MessageBox.Show(exception.Message);
 

我希望我的应用能够像这样以 XML 格式输入文件,并将它们的数据转换为我可以使用的类。

反序列化创建的对象“输入”使每个数据都正确,除了区域,那些在 XML 中具有“行”标签的区域。这些“行”每次都可能或多或少 4。

如何将带有行标签的项目反序列化并输入到 Zones_Points 列表或数组中?

【问题讨论】:

标签为什么要编号? 老实说,无论是谁设计了那个 xml 布局(又是 &lt;Row1&gt;&lt;Row2&gt; 等)都需要交谈;这只是一个糟糕的想法(xml 已经是位置性的,至少对于元素(不太常见的属性)而言),它会让你的生活变得艰难;结果,您将不得不以艰难的方式做很多事情。例如,有没有可能通过转换(也许是 xslt,尽管目前这不是“时尚”)来运行它,只使用 &lt;Row&gt; 的东西? Marc 碰到了痛处,你的 xml 不适合 XmlSerializer。默认序列化程序doesn't support wildcard names。 Preprocess the data 或实现自定义序列化程序。 感谢大家的回答!我不制作 XML 文件。它们是由旧软件生成的,但我需要我的应用程序能够从这些软件中输入数据。读取文件时是否应该将每个 Row* 重命名为 Row?之后我该怎么办? ***.com/a/67035760/5045688 - 使用自定义 XmlReader 【参考方案1】:

使用 IXmlSerializable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml.Linq;

namespace ConsoleApplication2

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            XmlReader reader = XmlReader.Create(FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(XML_Settings));
            XML_Settings settings = (XML_Settings)serializer.Deserialize(reader);
  
        
    
    [XmlRoot("Settings")]
    public class XML_Settings
    


        [XmlElement(ElementName = "FileName")]
        public string FileName  get; set; 

        [XmlElement(ElementName = "Zones")]
        public Zones_Points Zones_Point  get; set; 
        [XmlElement(ElementName = "Network_IP")]
        public string NetworkIP  get; set; 
        [XmlElement(ElementName = "Ethernet_Enable")]
        public bool EthernetEnable  get; set; 
        [XmlElement(ElementName = "Language")]
        public int Language  get; set; 
    
    public partial class Zones_Points : IXmlSerializable
    
        // Xml Serialization Infrastructure
        [XmlElement(ElementName = "Zones")]
        public List<Zones_Point> Points  get; set; 

        public void WriteXml(XmlWriter writer)
        
        

        public void ReadXml(XmlReader reader)
        

            XElement zones = (XElement)XElement.ReadFrom(reader);
            Points = new List<Zones_Point>();
            foreach (XElement row in zones.Elements())
            
                Zones_Point Point = new Zones_Point();
                Points.Add(Point);
                Point.Address = (int)row.Element("Address");
                Point.PointZone = (int)row.Element("Zone");
                Point.Installed = (Boolean)row.Element("Installed");
            

        

        public XmlSchema GetSchema()
        
            return (null);
        
    
    public partial class Zones_Point
    
        [XmlElement(ElementName = "Address")]
        public int Address  get; set; 
        [XmlElement(ElementName = "Zone")]
        public int PointZone  get; set; 
        [XmlElement(ElementName = "Installed")]
        public bool Installed  get; set; 
    

【讨论】:

以上是关于反序列化具有不同标签的 XML 相同项目的主要内容,如果未能解决你的问题,请参考以下文章

XML反序列化处理具有默认值的空标签

如何反序列化具有相同名称但不同类型的 API 响应

如何将不同名称的 XML 节点反序列化为相同的基本类型

C#中具有复杂元素的Xml反序列化[重复]

使用Jackson在android中反序列化具有相同键但不同类型的json

XML 反序列化:在单个属性上使用 XmlAttribute 和 XmlText