当XML具有多个相同名称的元素时,如何将XML表示为类

时间:2018-11-19 22:18:36

标签: c# xml xmlserializer

假设我们有以下xml。

<Company>
  <Tables>
    <Agri>
      <Tables>
        <Table Id="1">
        </Table>
      </Tables>
      <Tables>
        <Table Id="2">
        </Table>
      </Tables>
    </Agri>
    <Tables>
      <Table Id="3">
      </Table>
    </Tables>
    <Tables>
      <Table Id="4">
      </Table>
    </Tables>
  </Tables>
</Company>

如何将此类xml表示为类?

我已经尝试过类似的操作,但是似乎没有用。

void Test()
{
    string xml = //...
    using (var reader = new StringReader(xml))
    {
        var company = (Company)new XmlSerializer(typeof(Company)).Deserialize(reader);
    }
}

public class Company
{
    public CompanyTables Tables { get; set; }
}
public class CompanyTables
{
    [XmlArray]
    public Table[] Tables { get; set; }
}
public class Table
{
    [XmlAttribute("Id")]
    public string Id { get; set; }
}

这是我到目前为止可以得到的。

enter image description here

我当时以为它将用两个CompanyTable.Tables实例(Table 3和4)填充Id

我现在暂时忽略Agri元素,只是为了更好地反映xml的实际结构而在此处显示。

我会继续努力,但可以提供任何帮助。谢谢!

3 个答案:

答案 0 :(得分:1)

Table类包含在Tables类中。因此,您的Tables类应具有自身的“内部”集合(Tables

public class Company
{
    public List<Tables> Tables { get; set; }
}

// As you said Agri type ignored for now
public class Tables
{
    public Table Table { get; set; } // Use collection if Table can be more the one

    [XmlElement("Tables")]
    public Tables InnerTables { get; set; }
}

public class Table
{
    [XmlAttribute]
    public string Id { get; set; }
}

测试

private T DeserialzeFrom<T>(string xml)
{
    using (var reader = new StringReader(xml))
    {
        return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
    }
}

[Test]
public void ShouldDeserializeCompany()
{
    var xml = // Build xml string;

    // Expected deserialized object
    var expected = new Company
    {
        Tables = new List<Tables>
        {
            new Tables { Table = new Table { Id = "3" }},
            new Tables { Table = new Table { Id = "4" }}
        }
    };

    var actual = DeserialzeFrom<Company>(xml);

    actual.ShouldBeEquivalentTo(expected); // Test passing
}

答案 1 :(得分:1)

我认为这是您需要的类结构。通过这种结构,我已经序列化了数据,从而得到了匹配的XML输出。在上面反序列化您的xml也可以。

public class Company
{
    public Company()
    {
        this.Tables = new CompanyTables();
    }

    [XmlElement]
    public CompanyTables Tables { get; set; }
}

public class CompanyTables
{
    public CompanyTables()
    {
        this.Agri = new Agri();
    }

    [XmlElement]
    public TablesArr[] Tables { get; set; }

    [XmlElement]
    public Agri Agri { get; set; }
}

public class Agri
{
    public Agri() { }

    [XmlElementAttribute("Tables")]
    public TablesArr[] Tables { get; set; }
}

public class TablesArr
{
    public TablesArr() { }

    [XmlElementAttribute("Table")]
    public Table[] Tables { get; set; }
}

public class Table
{
    public Table() { }

    [XmlAttribute("Id")]
    public int Id { get; set; }
}

序列化测试:

string xml = "<Company><Tables><Agri><Tables><Table Id=\"1\"></Table></Tables><Tables><Table Id=\"2\"></Table></Tables></Agri><Tables><Table Id=\"3\"></Table></Tables><Tables><Table Id=\"4\"></Table></Tables></Tables></Company>";

XmlSerializer sx = new XmlSerializer(typeof(Company));

Company company = null;
using (MemoryStream ms = new MemoryStream())
{
    ms.Write(Encoding.UTF8.GetBytes(xml), 0, Encoding.UTF8.GetBytes(xml).Length);

    ms.Flush();

    ms.Seek(0, SeekOrigin.Begin);

    company = (Company)sx.Deserialize(ms);
}

反序列化测试:

Company company = new TestBed.Company();

company.Tables.Agri.Tables = new TablesArr[2];
company.Tables.Agri.Tables[0] = new TablesArr();
company.Tables.Agri.Tables[0].Tables = new Table[1];
company.Tables.Agri.Tables[0].Tables[0] = new Table() { Id=1 };
company.Tables.Agri.Tables[1] = new TablesArr();
company.Tables.Agri.Tables[1].Tables = new Table[1];
company.Tables.Agri.Tables[1].Tables[0] = new Table() { Id=2 };

company.Tables.Tables = new TablesArr[2];
company.Tables.Tables[0] = new TablesArr();
company.Tables.Tables[0].Tables = new Table[1];
company.Tables.Tables[0].Tables[0] = new TestBed.Table() { Id=3 };

company.Tables.Tables[1] = new TablesArr();
company.Tables.Tables[1].Tables = new Table[1];
company.Tables.Tables[1].Tables[0] = new TestBed.Table() { Id=4 };


XmlSerializer sx = new XmlSerializer(company.GetType());

using (MemoryStream ms = new MemoryStream())
{
    sx.Serialize(ms, company);

    ms.Seek(0, SeekOrigin.Begin);

    Console.WriteLine("[{0}]", Encoding.UTF8.GetString(ms.ToArray()));
}

答案 2 :(得分:0)

根据@Fabio的回答,这就是我要包括的Agri

public class Company
{
    public CompanyTables Tables { get; set; }
}

public class CompanyTables
{
    [XmlElement]
    public List<Tables> Tables { get; set; }

    public List<Tables> Agri { get; set; }
}

public class Tables
{
    [XmlElement]
    public List<Table> Table { get; set; }
}

public class Table
{
    [XmlAttribute]
    public int Id { get; set; }
}