2012-07-17 197 views
1

我調用一個方法來獲取我的頁面[請參閱GetPages(String xmlFullFilePath)]。 FromXElement方法應該將LitePropertyData元素反序列化爲強類型LitePropertyData對象。相反,它失敗下列行:xml未能反序列化

return (T)xmlSerializer.Deserialize(memoryStream); 

,並提供了以下錯誤:

<LitePropertyData xmlns=''> was not expected.

我在做什麼錯?我已經包括我調用的方法和XML數據:

public static T FromXElement<T>(this XElement xElement) 
    { 
     using (var memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(xElement.ToString()))) 
     { 
      var xmlSerializer = new XmlSerializer(typeof(T)); 
      return (T)xmlSerializer.Deserialize(memoryStream); 
     } 
    } 


public static List<LitePageData> GetPages(String xmlFullFilePath) 
    { 
     XDocument document = XDocument.Load(xmlFullFilePath); 

     List<LitePageData> results = (from record in document.Descendants("row") 
             select new LitePageData 
             { 
              Guid = IsValid(record, "Guid") ? 
              record.Element("Guid").Value : 
              null, 
              ParentID = IsValid(record, "ParentID") ? 
               Convert.ToInt32(record.Element("ParentID").Value) : 
               (Int32?)null, 
              Created = Convert.ToDateTime(record.Element("Created").Value), 
              Changed = Convert.ToDateTime(record.Element("Changed").Value), 
              Name = record.Element("Name").Value, 
              ID = Convert.ToInt32(record.Element("ID").Value), 
              LitePageTypeID = IsValid(record, "ParentID") ? 
               Convert.ToInt32(record.Element("ParentID").Value) : 
               (Int32?)null, 
              Html = record.Element("Html").Value, 
              FriendlyName = record.Element("FriendlyName").Value, 
              Properties = record.Element("Properties") != null ? record.Element("Properties").Element("LitePropertyData").FromXElement<List<LitePropertyData>>() : 
              new List<LitePropertyData>() 
             }).ToList(); 

     return results; 
    } 

這裏是XML:

<?xml version="1.0" encoding="utf-8"?> <root> <rows> 
<row> 
    <ID>1</ID> 
    <ImageUrl></ImageUrl> 
    <Html>Home page</Html> 
    <Created>01-01-2012</Created> 
    <Changed>01-01-2012</Changed> 
    <Name>Home page</Name> 
    <FriendlyName>home-page</FriendlyName> 
</row> 
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Guid>edeaf468-f490-4271-bf4d-be145bc6a1fd</Guid> 
    <ID>8</ID> 
    <Name>Unused</Name> 
    <ParentID>1</ParentID> 
    <Created>2006-03-25T10:57:17</Created> 
    <Changed>2012-07-17T12:24:30.0984747+01:00</Changed> 
    <ChangedBy /> 
    <LitePageTypeID xsi:nil="true" /> 
    <Html> 
    What is the purpose of this option? This option checks the current document for accessibility issues. It uses Bobby to provide details of whether the current web page conforms to W3C's WCAG criteria for web content accessibility. 


    Issues with Bobby and Cynthia 

    Bobby and Cynthia are free services that supposedly allow a user to expose web page accessibility barriers. It is something of a guide but perhaps a blunt instrument. I tested a few of the webpages that I have designed. Sure enough, my pages fall short and for good reason. I am not about to claim that Bobby and Cynthia are useless. Although it is useful and commendable tool, it project appears to be overly ambitious. Nevertheless, let me explain my issues with Bobby and Cynthia: 

    First, certain W3C standards for designing web documents are often too strict and unworkable. For instance, in some versions W3C standards for HTML, certain tags should not include a particular attribute, whereas in others they are requisite if the document is to be ???well-formed???. The standard that a designer chooses is determined usually by the requirements specification document. This specifies which browsers and versions of those browsers that the web page is expected to correctly display. Forcing a hypertext document to conform strictly to a specific W3C standard for HTML is often no simple task. In the worst case, it cannot conform without losing some aesthetics or accessibility functionality. 

    Second, the case of HTML documents is not an isolated case. Standards for XML, XSL, JavaScript, VBScript, are analogous. Therefore, you might imagine the problems when you begin to combine these languages and formats in an HTML document. 

    Third, there is always more than one way to skin a cat. For example, Bobby and Cynthia may flag those IMG tags that do not contain a TITLE attribute. There might be good reason that a web developer chooses not to include the title attribute. The title attribute has a limited numbers of characters and does not support carriage returns. This is a major defect in the design of this tag. In fact, before the TITLE attribute was supported, there was the ALT attribute. Most browsers support both, yet they both perform a similar function. However, both attributes share the same deficiencies. In practice, there are instances where neither attribute would be used. Instead, for example, the developer would write some JavaScript or VBScript to circumvent these deficiencies. The concern is that Bobby and Cynthia would not notice this because it does not ???understand??? what the JavaScript does. 
    </Html> 
    <FriendlyName>unused</FriendlyName> 
    <IsDeleted>false</IsDeleted> 
    <Properties> 
    <LitePropertyData> 
     <Description>Image for the page</Description> 
     <DisplayEditUI>true</DisplayEditUI> 
     <OwnerTab>1</OwnerTab> 
     <DisplayName>Image Url</DisplayName> 
     <FieldOrder>1</FieldOrder> 
     <IsRequired>false</IsRequired> 
     <Name>ImageUrl</Name> 
     <IsModified>false</IsModified> 
     <ParentPageID>3</ParentPageID> 
     <Type>String</Type> 
     <Value xsi:type="xsd:string">smarter.jpg</Value> 
    </LitePropertyData> 
    <LitePropertyData> 
     <Description>WebItemApplicationEnum</Description> 
     <DisplayEditUI>true</DisplayEditUI> 
     <OwnerTab>1</OwnerTab> 
     <DisplayName>WebItemApplicationEnum</DisplayName> 
     <FieldOrder>1</FieldOrder> 
     <IsRequired>false</IsRequired> 
     <Name>WebItemApplicationEnum</Name> 
     <IsModified>false</IsModified> 
     <ParentPageID>3</ParentPageID> 
     <Type>Number</Type> 
     <Value xsi:type="xsd:string">1</Value> 
    </LitePropertyData> 
    </Properties> 
    <Seo> 
    <Author>Phil Carney</Author> 
    <Classification /> 
    <Copyright>Carnotaurus</Copyright> 
    <Description> 
     What is the purpose of this option? This option checks the current document for accessibility issues. It uses Bobby to provide details of whether the current web page conforms to W3C's WCAG criteria for web content accessibility. 


     Issues with Bobby and Cynthia 

     Bobby and Cynthia are free services that supposedly allow a user to expose web page accessibility barriers. It is something of a guide but perhaps a blunt instrument. I tested a few of the webpages that I have designed. Sure enough, my pages fall short and for good reason. I am not about to claim that Bobby and Cynthia are useless. Although it is useful and commendable tool, it project appears to be overly ambitious. Nevertheless, let me explain my issues with Bobby and Cynthia: 

     First, certain W3C standards for designing web documents are often too strict and unworkable. For instance, in some versions W3C standards for HTML, certain tags should not include a particular attribute, whereas in others they are requisite if the document is to be ???well-formed???. The standard that a designer chooses is determined usually by the requirements specification document. This specifies which browsers and versions of those browsers that the web page is expected to correctly display. Forcing a hypertext document to conform strictly to a specific W3C standard for HTML is often no simple task. In the worst case, it cannot conform without losing some aesthetics or accessibility functionality. 

     Second, the case of HTML documents is not an isolated case. Standards for XML, XSL, JavaScript, VBScript, are analogous. Therefore, you might imagine the problems when you begin to combine these languages and formats in an HTML document. 

     Third, there is always more than one way to skin a cat. For example, Bobby and Cynthia may flag those IMG tags that do not contain a TITLE attribute. There might be good reason that a web developer chooses not to include the title attribute. The title attribute has a limited numbers of characters and does not support carriage returns. This is a major defect in the design of this tag. In fact, before the TITLE attribute was supported, there was the ALT attribute. Most browsers support both, yet they both perform a similar function. However, both attributes share the same deficiencies. In practice, there are instances where neither attribute would be used. Instead, for example, the developer would write some JavaScript or VBScript to circumvent these deficiencies. The concern is that Bobby and Cynthia would not notice this because it does not ???understand??? what the JavaScript does. 
    </Description> 
    <Keywords>unused</Keywords> 
    <Title>unused</Title> 
    </Seo> 
</row> </rows> </root> 

編輯

這裏是我的實體:

public class LitePropertyData 
{ 

    public virtual string Description { get; set; } 
    public virtual bool DisplayEditUI { get; set; } 
    public int OwnerTab { get; set; } 
    public virtual string DisplayName { get; set; } 
    public int FieldOrder { get; set; } 
    public bool IsRequired { get; set; } 

    public string Name { get; set; } 
    public virtual bool IsModified { get; set; } 
    public virtual int ParentPageID { get; set; } 
    public LiteDataType Type { get; set; } 
    public object Value { get; set; } 

} 

[Serializable] 
public class LitePageData 
{ 
    public String Guid { get; set; } 
    public Int32 ID { get; set; } 
    public String Name { get; set; } 
    public Int32? ParentID { get; set; } 
    public DateTime Created { get; set; } 
    public String CreatedBy { get; set; } 
    public DateTime Changed { get; set; } 
    public String ChangedBy { get; set; } 
    public Int32? LitePageTypeID { get; set; } 
    public String Html { get; set; } 
    public String FriendlyName { get; set; } 
    public Boolean IsDeleted { get; set; } 
    public List<LitePropertyData> Properties { get; set; } 
    public LiteSeoPageData Seo { get; set; } 

    /// <summary> 
    /// Saves the specified XML full file path. 
    /// </summary> 
    /// <param name="xmlFullFilePath">The XML full file path.</param> 
    public void Save(String xmlFullFilePath) 
    { 
     XDocument doc = XDocument.Load(xmlFullFilePath); 

     XElement demoNode = this.ToXElement<LitePageData>(); 

     demoNode.Name = "row"; 

     doc.Descendants("rows").Single().Add(demoNode); 

     doc.Save(xmlFullFilePath); 
    } 

} 
+0

難道你想序列化的一些數據沒有被正確地轉換?你試圖序列化的數據中是否有可空類型?我不知道我是否在這裏看到所有的代碼,所以我不知道我是否錯過了一些東西。 – 2012-07-17 16:59:43

+0

好吧,我會分頁我的實體 – CarneyCode 2012-07-17 17:17:50

+0

我現在已經添加了上面的實體。我認爲現在有足夠的信息來重現問題。 – CarneyCode 2012-07-17 17:22:30

回答

0

我重構了將屬性獲取到GetProperties方法的邏輯。然後註釋掉原代碼來填充方法GETPAGES內屬性,調用新方法之前:

public static List<LitePropertyData> GetProperties(XElement record) 
    { 
     if (record.Element("Properties") == null) return new List<LitePropertyData>(); 
     if (record.Descendants("Properties")== null) return new List<LitePropertyData>(); 
     if (record.Descendants("Properties").Descendants("LitePropertyData") == null) return new List<LitePropertyData>(); 

     List<LitePropertyData> properties = 
     (from property in record.Descendants("Properties").Descendants("LitePropertyData") 
     select new LitePropertyData 
     { 
      Description = property.Element("Description").Value, 
      DisplayEditUI = property.Element("DisplayEditUI").Value.ToBoolean(), 
      DisplayName = property.Element("DisplayName").Value, 
      FieldOrder = property.Element("FieldOrder").Value.ToInt32(), 
      IsModified = property.Element("IsModified").Value.ToBoolean(), 
      IsRequired = property.Element("IsRequired").Value.ToBoolean(), 
      Name = property.Element("Name").Value, 
      OwnerTab = property.Element("OwnerTab").Value.ToInt32(), 
      ParentPageID = property.Element("ParentPageID").Value.ToInt32(), 
      Type = (LiteDataType)property.Element("Type").Value.ToInt32(), 
      Value = property.Element("Value").Value, 
     }).ToList(); 

     return properties; 
    } 


    /// <summary> 
    /// Gets the pages. 
    /// </summary> 
    /// <param name="xmlFullFilePath">The XML full file path.</param> 
    /// <returns></returns> 
    public static List<LitePageData> GetPages(String xmlFullFilePath) 
    { 
     XDocument document = XDocument.Load(xmlFullFilePath); 

     List<LitePageData> results = (from record in document.Descendants("row") 
             select new LitePageData 
             { 
              Guid = IsValid(record, "Guid") ? 
              record.Element("Guid").Value : 
              null, 
              ParentID = IsValid(record, "ParentID") ? 
               Convert.ToInt32(record.Element("ParentID").Value) : 
               (Int32?)null, 
              Created = Convert.ToDateTime(record.Element("Created").Value), 
              Changed = Convert.ToDateTime(record.Element("Changed").Value), 
              Name = record.Element("Name").Value, 
              ID = Convert.ToInt32(record.Element("ID").Value), 
              LitePageTypeID = IsValid(record, "ParentID") ? 
               Convert.ToInt32(record.Element("ParentID").Value) : 
               (Int32?)null, 
              Html = record.Element("Html").Value, 
              FriendlyName = record.Element("FriendlyName").Value, 
              Properties = GetProperties(record), 
              //record.Element("Properties") != null ? record.Element("Properties").FromXElement<List<LitePropertyData>>() : 
              // new List<LitePropertyData>() 
             }).ToList(); 

     return results; 
    } 
1

我的建議是在.NET中創建對象,然後將其序列化爲XML,然後將l ook以.NET創建的有效xml格式。然後讓你的XML看起來像這樣。

此方法會將LitePageData對象轉換爲XML。如果你想檢查它,你可以將有效的xml保存到一個文件或其他東西,或者只是將其轉儲出來。

public static XElement GetXElementFromLitePageData(LitePageData objectToSerialize) 
{ 
    var xmlSerializer = new XmlSerializer(typeof(LitePageData)); 
    var doc = new XDocument(); 
    using (XmlWriter xmlWriter = doc.CreateWriter()) 
    { 
     xmlSerializer.Serialize(xmlWriter, objectToSerialize); 
    } 

    return doc.Root; 
} 
+0

'SerializableAttribute'與'XmlSerializer'無關。 – 2012-07-19 01:38:29

+0

xml已經是一個轉儲。 – CarneyCode 2012-07-22 08:21:23

1

我實現了你的類,然後序列化頁面數據對象,並能夠序列化爲XML和回。 如果你可以在.NET中創建你的對象,然後序列化它,你應該得到有效的XML。確保在嘗試反序列化時XML的格式如此。

我花了一些調戲你沒有提供實體但被引用:

[Serializable] 
public class LitePropertyData 
{ 

    public virtual string Description { get; set; } 
    public virtual bool DisplayEditUI { get; set; } 
    public int OwnerTab { get; set; } 
    public virtual string DisplayName { get; set; } 
    public int FieldOrder { get; set; } 
    public bool IsRequired { get; set; } 
    public string Name { get; set; } 
    public virtual bool IsModified { get; set; } 
    public virtual int ParentPageID { get; set; } 
    public LiteDataType Type { get; set; } 
    public object Value { get; set; } 
} 

[Serializable] 
public enum LiteDataType 
{ 
    String, 
    NotString, 
} 

[Serializable] 
public class LitePageData 
{ 
    public String Guid { get; set; } 
    public Int32 ID { get; set; } 
    public String Name { get; set; } 
    public Int32? ParentID { get; set; } 
    public DateTime Created { get; set; } 
    public String CreatedBy { get; set; } 
    public DateTime Changed { get; set; } 
    public String ChangedBy { get; set; } 
    public Int32? LitePageTypeID { get; set; } 
    public String Html { get; set; } 
    public String FriendlyName { get; set; } 
    public Boolean IsDeleted { get; set; } 
    public List<LitePropertyData> Properties { get; set; } 
    public LiteSeoPageData Seo { get; set; } 
} 

[Serializable] 
public class LiteSeoPageData 
{ 
    public string Author { get; set; } 
    public string Classification { get; set; } 
    public string CopyRight { get; set; } 
    public string Description { get; set; } 
    public string Keywords { get; set; } 
    public string Title { get; set; } 
} 

程序是這樣的:

 static void Main(string[] args) 
    { 
     var type = LiteDataType.String; 
     var data1 = new LitePropertyData 
     { 
      Description = "LitePropertyData Description", 
      DisplayEditUI = true, 
      OwnerTab = 1, 
      DisplayName = "LitePropertyData Display Name", 
      FieldOrder = 2, 
      IsRequired = true, 
      Name = "LitePropertyData Name", 
      IsModified = false, 
      ParentPageID = 3, 
      Type = type, 
      Value = "LitePropertyData value" 
     }; 

     var data2 = new LitePropertyData 
     { 
      Description = "LitePropertyData Description2", 
      DisplayEditUI = false, 
      OwnerTab = 4, 
      DisplayName = "LitePropertyData Display Name2", 
      FieldOrder = 5, 
      IsRequired = false, 
      Name = "LitePropertyData Name2", 
      IsModified = false, 
      ParentPageID = 6, 
      Type = type, 
      Value = "LitePropertyData value2" 
     }; 

     var seo = new LiteSeoPageData 
     { 
      Author = "Seo Author", 
      Classification = "Seo class", 
      CopyRight = "Seo copyright", 
      Description = "Seo desc", 
      Keywords = "Seo keywords", 
      Title = "Seo Title" 
     }; 

     var pageData = new LitePageData 
     { 
      Guid = Guid.NewGuid().ToString(), 
      ID = 7, 
      Name = "page data name", 
      ParentID = null, 
      Created = DateTime.Now, 
      CreatedBy = "me", 
      Changed = DateTime.UtcNow, 
      LitePageTypeID = 9, 
      Html = "this is not html", 
      FriendlyName = "casper", 
      IsDeleted = false, 
      Properties = new List<LitePropertyData> { data1, data2 }, 
      Seo = seo 
     }; 

     XElement xml = GetXElementFromLitePageData(pageData); 
     Save(@"C:\Users\Public\Documents\pageData2.xml", xml); 

     LitePageData deserializedPageData = GetLitePageDataFromXElement(xml); 

     Console.ReadLine(); 
    } 

    /// <summary> 
    /// Saves the specified XML full file path. 
    /// </summary> 
    /// <param name="xmlFullFilePath">The XML full file path.</param> 
    public static void Save(String xmlFullFilePath, XElement xml) 
    { 
     var doc = new XDocument(); 
     doc.Add(xml); 
     doc.Save(xmlFullFilePath); 
    } 

    public static XElement GetXElementFromLitePageData(LitePageData objectToSerialize) 
    { 
     var xmlSerializer = new XmlSerializer(typeof(LitePageData)); 
     var doc = new XDocument(); 
     using (XmlWriter xmlWriter = doc.CreateWriter()) 
     { 
      xmlSerializer.Serialize(xmlWriter, objectToSerialize); 
     } 

     return doc.Root; 
    } 

    public static LitePageData GetLitePageDataFromXElement(XElement xml) 
    { 
     var xmlSerializer = new XmlSerializer(typeof(LitePageData)); 
     return (LitePageData)xmlSerializer.Deserialize(xml.CreateReader()); 
    } 

這裏的XML:

<?xml version="1.0" encoding="utf-8"?> 
<LitePageData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Guid>d5a94c0e-b39a-4bd0-9db3-4aa9c4273144</Guid> 
    <ID>7</ID> 
    <Name>page data name</Name> 
    <ParentID xsi:nil="true" /> 
    <Created>2012-07-18T22:00:33.4522654-04:00</Created> 
    <CreatedBy>me</CreatedBy> 
    <Changed>2012-07-19T02:00:33.4532679Z</Changed> 
    <LitePageTypeID>9</LitePageTypeID> 
    <Html>this is not html</Html> 
    <FriendlyName>casper</FriendlyName> 
    <IsDeleted>false</IsDeleted> 
    <Properties> 
    <LitePropertyData> 
     <Description>LitePropertyData Description</Description> 
     <DisplayEditUI>true</DisplayEditUI> 
     <OwnerTab>1</OwnerTab> 
     <DisplayName>LitePropertyData Display Name</DisplayName> 
     <FieldOrder>2</FieldOrder> 
     <IsRequired>true</IsRequired> 
     <Name>LitePropertyData Name</Name> 
     <IsModified>false</IsModified> 
     <ParentPageID>3</ParentPageID> 
     <Type>String</Type> 
     <Value xsi:type="xsd:string">LitePropertyData value</Value> 
    </LitePropertyData> 
    <LitePropertyData> 
     <Description>LitePropertyData Description2</Description> 
     <DisplayEditUI>false</DisplayEditUI> 
     <OwnerTab>4</OwnerTab> 
     <DisplayName>LitePropertyData Display Name2</DisplayName> 
     <FieldOrder>5</FieldOrder> 
     <IsRequired>false</IsRequired> 
     <Name>LitePropertyData Name2</Name> 
     <IsModified>false</IsModified> 
     <ParentPageID>6</ParentPageID> 
     <Type>String</Type> 
     <Value xsi:type="xsd:string">LitePropertyData value2</Value> 
    </LitePropertyData> 
    </Properties> 
    <Seo> 
    <Author>Seo Author</Author> 
    <Classification>Seo class</Classification> 
    <CopyRight>Seo copyright</CopyRight> 
    <Description>Seo desc</Description> 
    <Keywords>Seo keywords</Keywords> 
    <Title>Seo Title</Title> 
    </Seo> 
</LitePageData> 
+0

+1我打算在週末檢查這個 – CarneyCode 2012-07-19 05:25:32

+0

一個公平的方法,但它沒有回答這個問題。我貼上了解決問題的答案。不管怎麼說,還是要謝謝你。 – CarneyCode 2012-07-22 08:23:52