2016-02-02 33 views
2

我有以下XML:.NET XML反序列化有着不同的價值觀

<results> 
<row> 
    <id>4990321</id> 
    <field name="First name">John</field> 
    <field name="Last name">Snow</field> 
    <field name="Country">USA</field> 
    <field name="City">San-Diego</field> 
    <field name="Postcode">123456</field> 
    <field name="Email">[email protected]</field> 
    <field name="Message">Hello</field> 
</row> 
<row> 
    ... 
<row> 
</results> 

我需要反序列化的對象數組:

public class Employee 
{ 
    public string Id { set; get; } 
    public string Firstname { set; get; } 
    public string Lastname { set; get; } 
    public string Country { set; get; } 
    public string City { set; get; } 
    public string Postcode { set; get; } 
    public string Email { set; get; } 
    public string Message { set; get; } 
} 

我試着使用來實現它XmlElementAttributeXmlAttributeAttribute,但屬性名爲ElementName不理解XPath,所以我無法獲得特定字段的值(如field[name='Email']

誰有什麼想法我該怎麼做?不需要XDocument解析。

+0

你有沒有嘗試過這樣的事情?:https://msdn.microsoft.com/en-us/library/bb387041.aspx – montewhizdoh

+0

@montewhizdoh使用LINQ我需要解析它。我在文章的最後寫道,我想避免XElement/XDocument。這對我的任務來說非常沉重。 – matterai

回答

1

一個建議是將數據預處理爲一種更友好的通過XSLT轉換進行序列化的表單。這可以在C#中通過XslCompiledTransform類完成。

使用示例XSL文件將是:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/> 
    <xsl:template match="results"> 
     <Employees> 
     <xsl:for-each select="row"> 
      <Employee> 
       <Id><xsl:value-of select="id" /></Id> 
       <Firstname><xsl:value-of select="field[@name='First name']" /></Firstname> 
       <Lastname><xsl:value-of select="field[@name='Last name']" /></Lastname> 
       <Country><xsl:value-of select="field[@name='Country']" /></Country> 
      </Employee> 
     </xsl:for-each> 
     </Employees> 
    </xsl:template> 
</xsl:stylesheet> 

(不完整,但足以說明目的)

在你的C#程序的改造很簡單:

var xslReader = XmlReader.Create(new StringReader(GetXslString())); 
var xmlReader = XmlReader.Create(new StringReader(GetXmlString())); 

var transformedStream = new MemoryStream(); 

var xmlWriter = XmlWriter.Create(transformedStream); 
var xslt = new XslCompiledTransform(); 

xslt.Load(xslReader); 
xslt.Transform(xmlReader, xmlWriter); 

transformedStream.Seek(0, SeekOrigin.Begin); 

// Use your transformedStream to deserialize the object 

.NET小提琴演示此代碼here

這是什麼? ñ對你的樣本數據,它產生類似輸出:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<Employees> 
    <Employee> 
     <Id>4990321</Id> 
     <Firstname>Jhon</Firstname> 
     <Lastname>Snow</Lastname> 
     <Country>USA</Country> 
    </Employee> 
    <Employee> 
     <Id>4990322</Id> 
     <Firstname>Mike</Firstname> 
     <Lastname>Ross</Lastname> 
     <Country>UK</Country> 
    </Employee> 
</Employees> 

這應該是相當容易的,現在對於任何默認反序列化工具來接管沒有先進的文件選擇器等

+0

這是個好主意。我不得不做類似的事情,但我使用Regex.replace來實現它... http://stackoverflow.com/questions/11778780/c-sharp-regex-help-replacing-patterns – montewhizdoh

0

你可以反序列化它通過明確聲明的順序元素反序列化使用Order

[XmlRoot("results")] 
public class Results 
{ 
    [XmlElement("row")] 
    public List<Employee> Employees { get; set; } 
} 

public class Employee 
{ 
    [XmlElement(ElementName = "id", Order = 1)] 
    public string Id { set; get; } 
    [XmlElement(ElementName = "field", Order = 2)] 
    public string Firstname { set; get; } 
    [XmlElement(ElementName = "field", Order = 3)] 
    public string Lastname { set; get; } 
    [XmlElement(ElementName = "field", Order = 4)] 
    public string Country { set; get; } 
    [XmlElement(ElementName = "field", Order = 5)] 
    public string City { set; get; } 
    [XmlElement(ElementName = "field", Order = 6)] 
    public string Postcode { set; get; } 
    [XmlElement(ElementName = "field", Order = 7)] 
    public string Email { set; get; } 
    [XmlElement(ElementName = "field", Order = 8)] 
    public string Message { set; get; } 
} 

然後,您可以反序列化這個如此(其中xml是你的XML字符串):

var results = new XmlSerializer(typeof(Results)).Deserialize(new StringReader(xml)); 
+0

嗯..這是很好的解決方案。但它會更好,如果它可以完成沒有綁定秩序=) – matterai

+0

所以檢查屬性名稱並使用它綁定?我認爲這是不可能的 - 儘管可以證明我錯了!也許創建自己的構造函數更合適,那麼如果這不合適? – TVOHM

+0

如果我想跳過一些點,並且只能得到1,2和7個元素到我的班級,那麼eour解決方案工作不正確。在預期的第一和第二個屬性中,我得到了正確的值,但是在第三個屬性中,我從第三個xml元素中獲得了值(但預計我得到了7)。所以對我來說有一個不好的解決方案。 – matterai