具有附加元数据的类属性的XML序列化

如何解决具有附加元数据的类属性的XML序列化

我有一个如下实体

C:\Users\YOURUSERNAME \ .gradle\caches

我想按以下顺序进行序列化

public class Vehicle{
    public int VehicleId {get;set;};
    public string Make {get;set;};
    public string Model{get;set;}
}

在Vehicle类中,我有大约100个这样的属性,对于每个车辆属性,我想附加一个元数据ApplieTo,这将对下游系统有所帮助。 AppliesTo属性为静态,其值在设计时定义。现在如何将AppliesTo元数据附加到每个属性,然后依次序列化为XML?

解决方法

您可以使用System.Xml.Linq中的XElement来实现此目的。由于您的数据是静态的,因此可以轻松分配它们。下面的示例代码-

XElement data= new XElement("Vehicle",new XElement("VehicleId",new XAttribute("AppliesTo","C1"),"1244"),new XElement("Make","Common"),"HXV"),new XElement("Model","C2"),"34 - 34")
               );
  //OUTPUT
  <Vehicle>
   <VehicleId AppliesTo="C1">1244</VehicleId>
   <Make AppliesTo="Common">HXV</Make>
   <Model AppliesTo="C2">34 - 34</Model>
  </Vehicle>

如果您对System.Xml.Linq不感兴趣,则可以选择XmlSerializer类。为此,您需要为vehicle的每个属性定义单独的类。以下是示例代码,您可以将其扩展为Make and Model-

[XmlRoot(ElementName = "VehicleId")]
public class VehicleId
{
    [XmlAttribute(AttributeName = "AppliesTo")]
    public string AppliesTo { get; set; }
    [XmlText]
    public string Text { get; set; }
}


[XmlRoot(ElementName = "Vehicle")]
public class Vehicle
{
    [XmlElement(ElementName = "VehicleId")]
    public VehicleId VehicleId { get; set; }
    //Add other properties here
}

然后创建测试数据并使用XmlSerializer类构造XML-

Vehicle vehicle = new Vehicle
         {
            VehicleId = new VehicleId
              {
                 Text = "1244",AppliesTo = "C1",}
         };

XmlSerializer testData = new XmlSerializer(typeof(Vehicle));            
var xml = "";

using (var sww = new StringWriter())
   {
      using (XmlWriter writer = XmlWriter.Create(sww))
       {
          testData.Serialize(writer,vehicle);
          xml = sww.ToString(); // XML 
       }
    }
,

以所需的方式使用默认的.NET XML序列化器(System.Xml.Serialization.XmlSerializer)并非易事或理想,但这是可能的。此答案显示了如何创建一个类结构来保存您的主数据和元数据,然后使用XmlAttributeAttribute标记属性,以便将其序列化为XML属性。

假设:

关于您要实现的实现有很多未知数,例如:

  • 您要使用的XML序列化程序(.NET的默认值?)
  • 注入“ AppliesTo”的机制(属性?)
  • 您关心反序列化吗?

此答案假定使用默认的.NET序列化程序,反序列化很重要,并且您不关心注入元数据的确切方法。

关键概念:

  1. 同时包含我们的主要属性值和元数据的通用类(请参见PropertyWithAppliesTo<T>
  2. 在通用类的元数据上使用XmlAttributeAttribute,因此将其作为XML属性写入父级属性
  3. 在通用类的主数据上使用XmlTextAttribute,因此将其写为父属性的Xml文本(而不是子属性)
  4. 对于要序列化的每个值,包括要序列化的主要类型(在这种情况下为Vehicle)上的两个属性:一种是使用元数据进行序列化的新通用类型,另一种是使用{ {1}}提供对属性值的“预期”访问
  5. 使用XmlIgnoreAttribute更改序列化属性的名称(使其与预期名称匹配)

代码:

XmlElementAttribute

运行时,字符串using System; using System.IO; using System.Xml.Serialization; namespace SomeNamespace { public class Program { static void Main() { var serializer = new XmlSerializer(typeof(Vehicle)); string s; var vehicle = new Vehicle { VehicleId = 1244 }; //serialize using (var writer = new StringWriter()) { serializer.Serialize(writer,vehicle); s = writer.ToString(); Console.WriteLine(s); } // edit the serialized string to test deserialization s = s.Replace("Common","C1"); //deserialize using (var reader = new StringReader(s)) { vehicle = (Vehicle)serializer.Deserialize(reader); Console.WriteLine($"AppliesTo attribute for VehicleId: {vehicle.VehicleIdMeta.AppliesTo}"); } } } public class Vehicle { [XmlElement(ElementName = "VehicleId")] // renames to remove the 'Meta' string public PropertyWithAppliesTo<int> VehicleIdMeta { get; set; } = new PropertyWithAppliesTo<int>("Common"); [XmlIgnore] // this value isn't serialized,but the property here for easy syntax public int VehicleId { get { return VehicleIdMeta.Value; } set { VehicleIdMeta.Value = value; } } } public class PropertyWithAppliesTo<T> { [XmlAttribute] // tells serializer this should be an attribute on this element,not a property public string AppliesTo { get; set; } = string.Empty; [XmlText] // tells serializer to not write this as a property,but as the main XML text public T Value { get; set; } = default; public PropertyWithAppliesTo() : this(string.Empty) { } public PropertyWithAppliesTo(string appliesTo) : this(appliesTo,default) { } public PropertyWithAppliesTo(string appliesTo,T initialValue) { AppliesTo = appliesTo; Value = initialValue; } } } 如下所示:

s

其他说明:

  • 您可以看到如何向<?xml version=\"1.0\" encoding=\"utf-16\"?> <Vehicle xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <VehicleId AppliesTo="Common">1244</VehicleId> </Vehicle> 添加更多属性:添加标记为Vehicle的类型PropertyWithAppliesTo<T>的属性以为其指定所需的名称,然后添加类型T的属性标记为XmlElement并环绕所需的XmlIgnore
  • 您可以通过更改Value的构造函数的输入并为其提供不同的元数据字符串来控制AppliesTo的值。
  • 如果您不希望库的使用者在IntelliSense中看到“元”属性,则可以使用EditorBrowsableAttribute。使用源和项目引用时,它不会对您隐藏任何东西;仅在引用编译的dll时隐藏。

诚然,这是向类添加属性的一种烦人的方法。但是,如果要使用默认的.NET XML序列化程序,则这是一种实现所需XML的方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res