繁体   English   中英

如何将没有属性的 XML 转换为 C# 属性?

[英]How can I convert an XML without attributes to C# properties?

我无法将我的 XML 转换为 C# object。

我的 XML 看起来像这样:

<metadata>
<item name="Date" type="xs:date"/>
<item name="Hour" type="xs:time"/>
<item name="Group" type="xs:string" length="12"/>
<item name="Status" type="xs:string" length="18"/>
</metadata>
<data>
<row>
<value>2020-05-08</value>
<value>14:00:01</value>
<value>A</value>
<value>Active</value>
</row>
<row>
<value>2020-05-08</value>
<value>14:00:01</value>
<value>B</value>
<value>Inactive</value>
</row>
</data>
</metadata>

我想 map XML 到 c# object 看起来像这样

public class GroupDto

    {
        public string Date { get; set; }
        public string Hour { get; set; }
        public string Group { get; set; }
        public string Status { get; set; }
    }

(日期和时间可以是字符串,没问题)我正在使用 JsonConvert.SerializeXmlNode(doc),但它给了我这个结果:

   "data": {
      "row": [
         {
            "value": [
               "2020-05-08",
               "14:00:01",
               "A",
               "Active"
            ]
         },
....

我喜欢将 map 的“值”改为 C# object 的相应属性。 有没有一种适当的方法可以使用这种奇怪格式的 XML 来实现这一目标?

如果无法将值与值区分开来,则必须为反序列化制定一些规则。

假设您根本不相信属性的顺序正确,您可以使用以下规则组:

  • Date 和 Hour 都可以解析为DateTime
  • 小时包含':'而日期不包含。
  • Group is only letter 或 Status 匹配已知状态列表
foreach(var row in data.Row){
    var temp = new GroupDto();
    foreach(var val in row.Value){

        if( DateTime.TryParse(val, out DateTime date) )
        {
            if(val.Contains(':')) //it should be a time
            {
                temp.Hour = date.ToShortTimeString(); //or keep the datetime format
            }
            else
            {
                temp.Hour = date.ToShortDateString();
            }           
        }

        //either based status on a list of know status
        else if(knowStatus.Contains(val))
        {
            temp.Status = val;
        }       
        //or base Group detection on string lenght and default the remaining possibility to status
        else if(val.lenght>1)
        {       
            temp.Status = val;
        }

        else {      
            temp.Group  = val;
        }
    }
    // return temp/ yeild return temp/ Add it to a list of result etc
}

请注意,这或多或少是基于无效 Xml 的伪代码。 这看起来就像一旦你添加一个公共根并在最后删除最后一个关闭元......:

[XmlRoot(ElementName="row")]
public class Row {
    [XmlElement(ElementName="value")]
    public List<string> Value { get; set; }
}

[XmlRoot(ElementName="data")]
public class Data {
    [XmlElement(ElementName="row")]
    public List<Row> Row { get; set; }
}

如果您信任属性订单,您可以简单地

Data.Row.Select(x => new GroupDto{
                Date = x.Value[0],
                Hour = x.Value[1],
                Group = x.Value[2],
                Status = x.Value[3],
            } )

如果您不信任属性的顺序,可以尝试以下操作:

var metadata = doc.Root.Element("metadata");

var mapper = metadata.Elements("item")
    .Select((i, c) => new { Property = i.Attribute("name").Value, Index = c })
    .ToDictionary(i => i.Property, i => i.Index);

var rows = doc.Root.Element("data").Elements("row").Select(r => new GroupDto
{
    Date = r.Elements("value").ElementAt(mapper[nameof(GroupDto.Date)]).Value,
    Hour = r.Elements("value").ElementAt(mapper[nameof(GroupDto.Hour)]).Value,
    Group = r.Elements("value").ElementAt(mapper[nameof(GroupDto.Group)]).Value,
    Status = r.Elements("value").ElementAt(mapper[nameof(GroupDto.Status)]).Value,
}).ToList();

它可能不是最佳解决方案,但它以一种不那么复杂的方式为您提供了您想要的东西。

最重要的是,如果您在 xml 中的属性与您的 DTO object 的属性不匹配,您总是可以引入一个额外的映射层。 例如:

var metaMapper = metadata.Elements(ns + "item")
    .Select((i, c) => new { Property = i.Attribute("name").Value, Index = c })
    .ToDictionary(i => i.Property, i => i.Index);

var metaPropertyMapper = new Dictionary<string, string>
{
    {  nameof(GroupDto.Date),  "DateInXML" },
    {  nameof(GroupDto.Hour),  "HourInXML" },
    {  nameof(GroupDto.Group), "GroupInXML" },
    {  nameof(GroupDto.Status), "StatusInXML" },
};

var rows = doc.Root.Element(ns + "data").Elements(ns + "row").Select(r => new GroupDto
{
    Date = r.Elements(ns + "value").ElementAt(metaMapper[metaPropertyMapper[nameof(GroupDto.Date)]]).Value,
    Hour = r.Elements(ns + "value").ElementAt(metaMapper[metaPropertyMapper[nameof(GroupDto.Hour)]]).Value,
    Group = r.Elements(ns + "value").ElementAt(metaMapper[metaPropertyMapper[nameof(GroupDto.Group)]]).Value,
    Status = r.Elements(ns + "value").ElementAt(metaMapper[metaPropertyMapper[nameof(GroupDto.Status)]]).Value,
}).ToList();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM