【问题标题】:XmlSerializer C# array-like without wrapping collection-elementXmlSerializer C# 类数组,不包装集合元素
【发布时间】:2019-11-29 13:28:41
【问题描述】:

我正在尝试使用 C# 中的 XmlSerializer 解析外部 XML 文件,源 XML 看起来像这样:

<product>
  <id>71464280-6d57-49de-ba26-35c9919d808d</id>
  <name>Random Product</name>
  <property name="color">Blue</property>
  <property name="country">SE</property>
  <property name="brand">Fancy Brand</property>
</product>

我试图让它与 C# 类匹配,问题是“属性”元素,首先我将它们视为列表/数组,但我没有设法在没有包装的情况下解析它们像..这样的元素在源代码中,然后我开始认为它们可能是类上的属性,如下所示:

 public class ProductXml
{

    public Guid Id { get; set; }
    public string Name { get; set; }

    [XmlElement(ElementName = "Property")]
    public string Color { get; set; }

    [XmlElement(ElementName = "Property")]
    public string Country { get; set; }

    [XmlElement(ElementName = "Property")]
    public string Brand { get; set; }
}

这样的类是要序列化的,它不会呈现,因为有多个“属性”元素。

有人知道我应该如何处理这个问题吗?

谢谢!

【问题讨论】:

    标签: c# xml xml-serialization


    【解决方案1】:

    原来这很简单,只需要确保列表属性的元素名称与“属性”类的元素名称匹配。

    我使用这个很棒的实用程序https://xmltocsharp.azurewebsites.net/发现了这一点

    [XmlRoot(ElementName = "product")]
    public class Product
    {
        [XmlElement(ElementName = "id")]
        public string Id { get; set; }
    
        [XmlElement(ElementName = "name")]
        public string Name { get; set; }
    
        [XmlElement(ElementName = "property")]
        public List<Property> Property { get; set; }
    }
    
    [XmlRoot(ElementName = "property")]
    public class Property
    {
        [XmlAttribute(AttributeName = "name")]
        public string Name { get; set; }
        [XmlText]
        public string Text { get; set; }
    }
    

    【讨论】:

    • 正确的解决方案,错误的解释。 XmlElementAttribute 不仅重命名项目,在集合的情况下,它还“扁平化”集合。如果没有此属性,集合本身将首先获得一个标签,并且内部项目将更深一个 xml 级别。请注意,您有两个不同的东西称为属性,一个属性和一个类型名称。使用 XmlElement,您可以跳过属性名称,并设置类型名称(项目名称)。属性上的 XmlRoot-Tag 没有用,因为这不是 xml 文档的根。
    【解决方案2】:

    你可以这样做:

    <?xml version="1.0" encoding="UTF-8"?>
    <product>
      <id>71464280-6d57-49de-ba26-35c9919d808d</id>
      <name>Random Product</name>
      <property name="color">Blue</property>
      <property name="country">SE</property>
      <property name="brand">Fancy Brand</property>
    </product>
    
    public class Product
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Color { get; set; }
        public string Country { get; set; }
        public string Brand { get; set; }
    
        public Product(XElement element)
        {
            ID = element.Element("id").Value;
            Name = element.Element("name").Value;
            List<XElement> properties = element.Elements("property").ToList();
            Color = properties.Where(x => x.Attribute("name").Value == "color").First().Value;
            Country = properties.Where(x => x.Attribute("name").Value == "country").First().Value;
            Brand = properties.Where(x => x.Attribute("name").Value == "brand").First().Value;
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load("xml.xml");
            XElement productElement = doc.Descendants("product").First();
            Product product = new Product(productElement);
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是另一种获取单个属性值的方法

          public class ProductXml
          {
      
              public Guid Id { get; set; }
              public string Name { get; set; }
              private string Color { get; set; }
              private string Country { get; set; }
              private string Brand { get; set; }
      
              [XmlElement(ElementName = "Property")]
              public List<Property> property
              {
                  get {
                      return new List<Property>() {
                          new Property() { Name = "color", Text = Color},
                          new Property() { Name = "country", Text = Country},
                          new Property() { Name = "brand", Text = Brand},
                      };          
                  }
                  set {
                      foreach (Property prop in value)
                      {
                          switch (prop.Name)
                          {
                              case "color" :
                                  Color = prop.Text;
                                  break;
                              case "country":
                                  Country = prop.Text;
                                  break;
                              case "brand":
                                  Brand = prop.Text;
                                  break;
                          }
                      }
                  }
              }
          }
          [XmlRoot(ElementName = "property")]
          public class Property
          {
              [XmlAttribute(AttributeName = "name")]
              public string Name { get; set; }
              [XmlText]
              public string Text { get; set; }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-13
        • 2012-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多