如何将 XML 解析为自定义类



我有包含 xml 的字符串,我需要从中循环、解析和构建自定义类的实例化,以便插入到我的数据库中。

我需要的伪代码是这样的:

private List<SiteMapping> ExtractSiteMappingsFromXML(String xmlData)
{
    List<SiteMapping> sitemaps = new List<SiteMapping>();
    // parse xmlData, dynamically instantiating a SiteMapping class for each SiteMapping "record" 
in the xml
    foreach (record rec in xmlData)
    {
        SiteMapping sm = new SiteMapping();
        sm.Id = //current id found in the xml data
        sm.siteName = // current site name found in the xml data
        . . .
        sitemaps.Add(sm);
    }
    return sitemaps;
}

然后,ExtractSiteMappingsFromXML() 的调用者将遍历返回的 SiteMapping 列表,并将记录插入数据库。

根据我从这里得到的一个想法,我认为这样的事情可能是可能的:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlData);
XmlNodeList _ids = doc.GetElementsByTagName("Id");
XmlNodeList _sitenames = doc.GetElementsByTagName("siteName");
. . . // add an XmlNodeList for each element

然后我可以遍历 XmlNodeLists,如下所示:

for (int i = 0; i < _ids.Count; i++)
{
    SiteMapping sm = new SiteMapping();
    sm.Id =_ids[i];
    sm.siteName = _sitenames[i];
    . . . // add the rest
    sitemaps.Add(sm);
}

这合理吗?如果一个或多个元素具有空白值,这仍然有效吗?IOW,如果一个元素有时是空白的,它会在相应的 XmlNodeList 中添加一个空白值(这就是我想要的),还是会不添加任何内容,从而造成不匹配?

也许有一种优雅的 linqy(LINQ-to-XML)方法可以做到这一点?

注意:这是一个紧凑的框架应用程序,因此在实现方面存在这些限制。

更新

我想也许这段代码:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(omnivore);
List<SiteQuery> sitequeries =
  (from sitequery in xmlDoc.Descendants("SiteQuery")
   select new SiteQuery
   {
       Id = sitequery.Element("Id").Value,
       UPC_PackSize = sitequery.Element("UPC_PackSize").Value,
       UPC_Code = sitequery.Element("UPC_Code").Value,
   }).ToList<SiteQuery>();

。我从这里改编,可以解决问题,但我得到,"方法'后代'没有重载需要 1 个参数"

更新 2

我试过这个(XDocument而不是XmlDocument):

XDocument xmlDoc = new XDocument();
XDocument.Parse(omnivore);
List<SiteQuery> sitequeries =
 (from sitequery in xmlDoc.Descendants("SiteQuery")
  select new SiteQuery
  {
      Id = Convert.ToInt32(sitequery.Element("Id").Value),
      UPC_PackSize = Convert.ToInt32(sitequery.Element("UPC_PackSize").Value),
      UPC_Code = sitequery.Element("UPC_Code").Value
  }).ToList<SiteQuery>();

对我来说,我不得不使用"XDocument.Parse(omnivore);"而不是"xmlDoc.Parse(omnivore);"似乎很奇怪,但编译器告诉我这是必要的......?!?

不过,毫不奇怪,在此代码运行后,站点查询的计数为 0......

更新 3

也许Nitin Aggarwal的代码可以工作(它确实可以编译),但是在运行时我得到:

System.InvalidOperationException was unhandled
  _HResult=-2146233079
  _message=There is an error in XML document (1, 2).
  HResult=-2146233079
  IsTransient=false
  Message=There is an error in XML document (1, 2).
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader). . .

可能只是XML不好;而且,我不知道这些喷气时代类是否在紧凑框架中可用(我已经在.NET 4.5.1测试应用程序中编译了它)。

更新 4

Vishal,为了回答你的问题,这是我尝试解析的XML:

<ArrayOfSiteQuery xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/CStore.DomainModels.HHS"><SiteQuery><Id>00006000002</Id><UPCPackSize>1</UPCPackSize><UPC_Code>00006000002</UPC_Code><crvId></crvId><dept>8</dept><description>ZZ</description><openQty>0.0</openQty><packSize>1</packSize><subDept>80</subDept><unitCost>1.25</unitCost><unitList>5.0</unitList><vendorId>CONFLICT</vendorId><vendorItem>123456</vendorItem></SiteQuery>
.  . . (beaucoup other SiteQuery "records")
<SiteQuery><Id>5705654</Id><UPCPackSize>1</UPCPackSize><UPC_Code>5705654</UPC_Code><crvId></crvId><dept>2</dept><description>what do you want</description><openQty>0.0</openQty><packSize>1</packSize><subDept>0</subDept><unitCost>0.55</unitCost><unitList>1.62</unitList><vendorId></vendorId><vendorItem></vendorItem></SiteQuery></ArrayOfSiteQuery>

我是否需要先去掉初步位(<ArrayOfSiteQuery xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/CStore.DomainModels.HHS">)和末尾的"关闭标记"()?

顺便说一句,"CStore.DomainModels.HHS"在服务器应用程序中,客户端可能不知道那是什么。

更新 5

查看字符串中的 xml 后,我发现它的内容与我的自定义类不匹配(它是相同的数据,但某些成员名称不同,并且它们彼此顺序不对),所以我更改了自定义类以匹配 xml:

public class SiteQuery
{
    public int Id { get; set; }
    public int UPCPackSize { get; set; }
    public String UPC_Code { get; set; }
    public String crvId { get; set; }
    public int dept { get; set; }
    public String description { get; set; }
    public Double openQty { get; set; }
    public int packSize { get; set; }
    public int subDept { get; set; }
    public Decimal unitCost { get; set; }
    public Decimal unitList { get; set; }
    public String vendorId { get; set; }
    public String vendorItem { get; set; }
}

。但我仍然得到同样的无效操作异常......

更新 6

即使我从 xml 中删除了序言和后导码,使其仅包含 SiteQuery "xml 记录",将其保存为文件并加载进行处理:

String testData = File.ReadAllText("siteQueryTest.txt");
XmlSerializer serializer = new XmlSerializer(typeof(List<SiteQuery>));
XmlReader reader = XmlReader.Create(new StringReader(testData));
List<SiteQuery> siteQueries;
siteQueries = (List<SiteQuery>)serializer.Deserialize(reader);

。我仍然收到运行时错误:

System.InvalidOperationException was unhandled
  _HResult=-2146233079
  _message=There is an error in XML document (1, 2).
  HResult=-2146233079
  IsTransient=false
  Message=There is an error in XML document (1, 2).
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
       at Sandbox.Form1.button56_Click(Object sender, EventArgs e) in c:HoldingTankSandboxForm1.cs:line 2061
    . . .
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read3_ArrayOfSiteQuery()
       InnerException: 

这怎么可能?"testData"字符串的内容是:

<SiteQuery><Id>00006000002</Id><UPCPackSize>1</UPCPackSize><UPC_Code>00006000002</UPC_Code><crvId></crvId><dept>8</dept><description>ZZ</description><openQty>0.0</openQty><packSize>1</packSize><subDept>80</subDept><unitCost>1.25</unitCost><unitList>5.0</unitList><vendorId>CONFLICT</vendorId><vendorItem>123456</vendorItem></SiteQuery>
. . . // a ton of other StieQuery records
<SiteQuery><Id>5705654</Id><UPCPackSize>1</UPCPackSize><UPC_Code>5705654</UPC_Code><crvId></crvId><dept>2</dept><description>what do you want</description><openQty>0.0</openQty><packSize>1</packSize><subDept>0</subDept><unitCost>0.55</unitCost><unitList>1.62</unitList><vendorId></vendorId><vendorItem></vendorItem></SiteQuery>

怎么会有"XML 文档 (1, 2) 中的错误"

第 1 行第 2 列是"S";"S"是怎么回事?我假设什么都没有,那么它期待什么,因为它也不喜欢"A"(来自<ArrayOfSiteQuery)?

更新 7

我预置:

<?xml version="1.0" encoding="UTF-8"?>

。到文件,我得到同样的错误,但现在它是 1,40(仍然是第一个"<SiteQuery>"中的"S")。

你可以试试这个:

           XmlSerializer serializer = new XmlSerializer(typeof(List<SiteMapping>)); 
            XmlReader reader = XmlReader.Create(new StringReader(xmlData));
            List<SiteMapping> siteMappings;
            siteMappings = (List<SiteMapping>)serializer.Deserialize(reader);

请让我知道这是否有效

相关内容

  • 没有找到相关文章

最新更新