簡體   English   中英

如何將XML解析為自定義類?

[英]How can XML be parsed into custom classes?

我有包含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)方法嗎?

注意:這是一個Compact Framework應用,因此在實現方面會受到這些限制。

UPDATE

我想也許是這樣的代碼:

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>();

...我從這里改編而成,可以解決問題,但是我得到:“ 方法'Descendants'的重載不接受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( omn​​ivore ); ”而不是“ 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可能只是壞的。 但是我也不知道這些緊湊型飛機是否可以在Compact Framework中使用(我已經在.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">初步的位( <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; }
}

...但是我仍然收到相同的InvalidOp異常...

更新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:\HoldingTank\Sandbox\Form1.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);

請讓我知道這是否有效

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM