使用Linq将XML字符串转换为对象列表

时间:2012-05-21 18:55:46

标签: linq-to-xml

我正在尝试使用Linq将XML字符串转换为.net对象的常规集合(我讨厌linq ...主要是因为我没有时间精确地了解它是如何工作的,因此,我总是感到困惑当事情出错时,地狱)。我希望有一种简单易用的方法,如XSD或其他东西,以及某种解串器和重新编译器......但是.net中似乎没有任何本机支持。所以我想,为什么不只使用Linq?大错。但无论如何,我想把这个字符串变成......

<?xml version="1.0" encoding="utf-16"?>
  <ArrayOfPopulation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Population>
  <id>3</id>
  <name>CHF</name>
  <description>FR Congestive Heart Failure</description>
  <createdDate>2011-10-25T04:00:00Z</createdDate>
  <createdUserID>WPS_ANEMIA_POP_OWNER</createdUserID>
  <modifiedDate>2011-10-31T04:00:00Z</modifiedDate>
  <modifiedUserID>WPS_ANEMIA_POP_OWNER</modifiedUserID>
  <isActive>true</isActive>
  <owner>
    <type>AD GROUP</type>
  </owner>   
  <owner>
    <type>ACCOUNT</type>
  </owner>
  <type>
    <name>ACO SURVEY</name>
  </type>
  </Population>
  <Population>
  <id>2</id>
  <name>COPD</name>
  <description>FR Chronic Obstructive Pulmonary Disease</description>
  <createdDate>2011-10-25T04:00:00Z</createdDate>
  <createdUserID>WPS_ANEMIA_POP_OWNER</createdUserID>
  <modifiedDate>2011-10-31T04:00:00Z</modifiedDate>
  <modifiedUserID>WPS_ANEMIA_POP_OWNER</modifiedUserID>
  <isActive>true</isActive>
  <owner>
    <domain>1UPMC-ACCT</domain>
    <name>InteropDev</name>
    <type>AD GROUP</type>
  </owner>
  <owner>
    <domain>1UPMC-ACCT</domain>
    <name>ACOPopulationUsers</name>
    <type>AD GROUP</type>
  </owner>
  <owner>
    <domain>1UPMC-ACCT</domain>
    <name>muesml</name>
    <type>ACCOUNT</type>
  </owner>
  <owner>
    <domain>1UPMC-ACCT</domain>
    <name>andersonjm</name>
    <type>ACCOUNT</type>
  </owner>
  <type>
    <name>ACO SURVEY</name>
  </type>
 </Population>
 </ArrayOfPopulation>

进入这些对象的数组......

public class PopulationModel
{
    public string populationID { set; get; }

    public string PopName { set; get; }

    public string Description { set; get; }

    public int PopulationType { set; get; }

    public int isActive { set; get; }

    //public List<XSLTACOData> patients { set; get; }
}

哪种看起来像这样...

public class PopulationsModel
{
    public List<PopulationModel> Populations { set; get; }
}

我无法使用此linq to XML查询执行此操作...

XDocument xDocument = XDocument.Parse(xmlFromSvc);
XElement elem = xDocument.Element("ArrayOfPopulation");
//client.GetOwnedPopulations();
IEnumerable<PopulationsModel> popModel = (IEnumerable<PopulationsModel>)
     (from templates in elem.Elements("Population")
      select new PopulationModel
      {
          populationID = templates.Attribute("id").Value,
          PopName = templates.Attribute("name").Value,
          Description = templates.Attribute("description").Value,
          PopulationType = int.Parse(templates.Attribute("").Value),
          isActive = int.Parse(templates.Attribute("isActive").Value)
      }).ToList();

我正式感到困惑。为什么这不起作用?还有,必须有一个更简单的方法来完成这项工作?这似乎是xsd和其他所有垃圾的完美之处。我或许在这里努力工作?

现在得到这个例外......

Unable to cast object of type  'System.Collections.Generic.List`1[FocusedReadMissionsRedux.Models.PopulationModel]' to type 'System.Collections.Generic.IEnumerable`1[FocusedReadMissionsRedux.Models.PopulationsModel]'.

这似乎是一个稍微合理的例外。

2 个答案:

答案 0 :(得分:4)

  

为什么这不起作用?

好吧,让我们来看看你在做什么。您已将templates作为<Population>元素,然后您将这样查询:

  populationID = templates.Attribute("id").Value,
  PopName = templates.Attribute("name").Value,
  Description = templates.Attribute("description").Value,
  PopulationType = int.Parse(templates.Attribute("").Value),
  isActive = int.Parse(templates.Attribute("isActive").Value)

请注意您如何在这里使用Attribute。现在看一下XML:

<Population>
  <id>3</id>
  <name>CHF</name>
  ...
</Population>

Population元素没有任何属性。它嵌套了元素。我没有详细检查,但更改Attribute来电Element次来电可能会解决除PopulationType以外的所有问题。 (目前尚不清楚 你试图从中获取它。)

请注意,XAttributeXElement的显式转化通常比int.Parse等更清晰。

答案 1 :(得分:2)

您尝试使用Attribute方法获取价值,当它们实际上是元素时。

尝试这个(我还没有测试过它):

XDocument xDocument = XDocument.Parse(xmlFromSvc);
XElement elem = xDocument.Element("ArrayOfPopulation");

var popModel = (from templates in elem.Elements("Population")
                select new PopulationModel
                {
                     populationID = (string)templates.Element("id"),
                     PopName = (string)templates.Element("name"),
                     Description = (string)templates.Element("description"),
                     PopulationType = (int)templates.Element("Type").Element("Name"),
                     isActive = (int)templates.Element("isActive")
                }).ToList();