XML将其解析为集合对象

时间:2014-11-19 18:56:00

标签: c# asp.net xml parsing object

我能够将以下XML解析为对象,感谢MikeH。

当我将XML文件解析为对象时,它只会将最后一行填入对象中。我怎样才能将所有行解析为集合对象。行应填充到集合中。在这种情况下,所有5条记录都应该在集合中,而不仅仅是最后一条记录()。我花了一天的大部分时间,我必须遗漏一些关于如何将所有行放入对象的内容。

  - <ROW>
    <CELL INDEX="0">033331111</CELL> 
    <CELL INDEX="1">Agency 5 LTD</CELL> 
    <CELL INDEX="2">14 Some AVENUE North Brook, FL 65432 3827</CELL> 
    <CELL INDEX="3">A</CELL> 
    <CELL INDEX="4">4412034564</CELL> 
    <CELL INDEX="5" /> 
    <CELL INDEX="6">A - Active</CELL> 
    <CELL INDEX="7">6/1/2008 12:00:00 AM</CELL> 
    </ROW>

使用Visual Studio 2012或更高版本: 将XML复制到剪贴板 在Visual Studio中:编辑 - &gt;选择性粘贴 - &gt;将XML粘贴为类 然后,您需要将数据从XML序列化到新创建的类中以创建新对象:

var myObject = LoadFromXmlString<DATA_PROVIDERS>(xmlData);

public static T LoadFromXmlString<T>(string xml)
{
  T retval = default(T);
  try
  {
    XmlSerializer s = new XmlSerializer(typeof(T));
    MemoryStream ms = new MemoryStream(ASCIIEncoding.Default.GetBytes(xml));
    retval = (T)s.Deserialize(ms);
    ms.Close(); 
  }
  catch (Exception ex)
  {
    ex.Data.Add("Xml String", xml);
    throw new Exception("Error loading from XML string.  See data.", ex);
  }
  return retval;

}


<?xml version="1.0" encoding="UTF-8" ?> 
-<DATA_PROVIDERS UID="Providers|REP" FORCE_REFRESH="FALSE" DATA_PROVIDER="" FORMATTED="FALSE" REFRESH="TRUE">
 -<DATA_PROVIDER NAME="Prov" SOURCE="Provider" DATE="11/18/2014" DURATION="9s" REFRESH="TRUE" CUBE="1">
  <COLUMN INDEX="0" ID="119" TYPE="String" FORMAT="">Prov ID</COLUMN> 
  <COLUMN INDEX="1" ID="118" TYPE="String" FORMAT="">Prov Name</COLUMN> 
  <COLUMN INDEX="2" ID="113" TYPE="String" FORMAT="">Address Info</COLUMN> 
  <COLUMN INDEX="3" ID="110" TYPE="String" FORMAT="">Enroll Status Code</COLUMN> 
  <COLUMN INDEX="4" ID="119" TYPE="String" FORMAT="">Phone</COLUMN> 
  <COLUMN INDEX="5" ID="110" TYPE="String" FORMAT="">Fax</COLUMN> 
  <COLUMN INDEX="6" ID="109" TYPE="String" FORMAT="">Provider Status</COLUMN> 
  <COLUMN INDEX="7" ID="150" TYPE="Date" FORMAT="m/d/yyyy h:mm:ss am/pm">Provider Start Date</COLUMN> 
  - <ROW>
    <CELL INDEX="0">004042111</CELL> 
    <CELL INDEX="1">CONTOSO West INC</CELL> 
    <CELL INDEX="2">1234 Random Rd. SOMECITY, ZZ 12345 9876</CELL> 
    <CELL INDEX="3">F</CELL> 
    <CELL INDEX="4">5555551234123</CELL> 
    <CELL INDEX="5">5555551234</CELL> 
    <CELL INDEX="6">F - Agency Action</CELL> 
    <CELL INDEX="7">5/31/2011 12:00:00 AM</CELL> 
    </ROW>
  - <ROW>
    <CELL INDEX="0">004011117</CELL> 
    <CELL INDEX="1">CONTOSO North INC</CELL> 
    <CELL INDEX="2">4321 Random Rd. SOMECITY, ZZ 12345 9876</CELL> 
    <CELL INDEX="3">F</CELL> 
    <CELL INDEX="4">5555551234123</CELL> 
    <CELL INDEX="5">5555551234</CELL> 
    <CELL INDEX="6">F - Agency Action</CELL> 
    <CELL INDEX="7">5/31/2011 12:00:00 AM</CELL> 
    </ROW>
  - <ROW>
    <CELL INDEX="0">033337111</CELL> 
    <CELL INDEX="1">Agency 3 INC</CELL> 
    <CELL INDEX="2">200 street 5F Cityabc, NY 12033</CELL> 
    <CELL INDEX="3">A</CELL> 
    <CELL INDEX="4">2128545555</CELL> 
    <CELL INDEX="5" />
    <CELL INDEX="6">A - Active</CELL> 
    <CELL INDEX="7">10/27/2003 12:00:00 AM</CELL> 
    </ROW>
  - <ROW>
    <CELL INDEX="0">033334111</CELL> 
    <CELL INDEX="1">Agency 4 LLC</CELL> 
    <CELL INDEX="2">419 street Town, CT 17033 3945</CELL> 
    <CELL INDEX="3">U</CELL> 
    <CELL INDEX="4" /> 
    <CELL INDEX="5">7172304056</CELL> 
    <CELL INDEX="6">X - Did Not Re-enroll</CELL> 
    <CELL INDEX="7">2/24/2009 12:00:00 AM</CELL> 
    </ROW>
  - <ROW>
    <CELL INDEX="0">033331111</CELL> 
    <CELL INDEX="1">Agency 5 LTD</CELL> 
    <CELL INDEX="2">14 Some AVENUE North Brook, FL 65432 3827</CELL> 
    <CELL INDEX="3">A</CELL> 
    <CELL INDEX="4">4412034564</CELL> 
    <CELL INDEX="5" /> 
    <CELL INDEX="6">A - Active</CELL> 
    <CELL INDEX="7">6/1/2008 12:00:00 AM</CELL> 
    </ROW>
 </DATA_PROVIDER>
</DATA_PROVIDERS>

1 个答案:

答案 0 :(得分:0)

您需要做的是使用XmlElement("CELLS")属性标记Cells集合,以通知XmlSerializer该集合应该序列化为一系列具有相同名称的元素,而不是带有嵌套子元素的单个元素,如下所示:

public class Cell
{
    [XmlText]
    public string Text { get; set; }

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

[XmlRoot("ROW")]
public class Row
{
    [XmlElement("CELL")]
    public List<Cell> Cells { get; set; }
}

此外,我注意到你的Cell对象包含它们的数组索引作为属性,这似乎是多余的,因为它的单元格列表中每个单元格的位置也传达了这些信息。您是否真的希望在运行时类中使用它 - 或者您是否愿意仅为序列化生成此信息?如果你更喜欢后者,你可以序列化&amp;将单元格反序列化为包含数组索引作为属性属性的代理数组,如下所示:

public class Cell 
{
    public Cell() {}

    public Cell(Cell other)
    {
        this.Text = other.Text;
    }

    [XmlText]
    public string Text { get; set; }
}

public class XmlCell : Cell // For serialization
{
    public XmlCell() : base() {}

    public XmlCell(Cell other, int index) : base(other)
    {
        this.Index = index;
    }

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

[XmlRoot("ROW")]
public class Row
{
    List<Cell> cells;

    [XmlIgnore]
    public List<Cell> Cells
    {
        get
        {
            if (cells == null)
                Interlocked.CompareExchange(ref cells, new List<Cell>(), null);
            return cells;
        }
    }

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    [XmlElement("CELL")]
    public XmlCell[] XmlCells // proxy array for serialization.
    {
        get
        {
            var xmlCells = new XmlCell[Cells.Count];
            for (int iCell = 0; iCell < xmlCells.Length; iCell++)
                xmlCells[iCell] = new XmlCell(Cells[iCell], iCell);
            return xmlCells;
        }
        set
        {
            Cells.Clear();
            foreach (var xmlCell in value)
            {
                Cells.EnsureCount(xmlCell.Index + 1);
                Cells[xmlCell.Index] = new Cell(xmlCell);
            }
        }
    }
}

最后有两种扩展方法:

public static class ListExtensions
{
    public static void Resize<T>(this List<T> list, int count)
    {
        if (list == null || count < 0)
            throw new ArgumentException();
        int oldCount = list.Count;
        if (count > oldCount)
        {
            list.Capacity = count;
            for (int i = oldCount; i < count; i++)
                list.Add(default(T));
        }
        else if (count < oldCount)
        {
            for (int i = oldCount - 1; i >= count; i--)
                list.RemoveAt(i);
        }
    }

    public static void EnsureCount<T>(this List<T> list, int count)
    {
        if (list == null || count < 0)
            throw new ArgumentException();
        if (count > list.Count)
            list.Resize(count);
    }
}