2015-12-11 133 views
2

我正在嘗試創建一個將C#類對象序列化爲XML的POST函數。使用C#對象的前綴和名稱空間

我非常困難的一部分是將命名空間前綴添加到子根元素的子項中,因此在本例中僅限contact子項。

我似乎能夠獲得contact的子元素的前綴的唯一方法是通過SerializerNamespace類添加它們,但是我只能將它附加到根元素CreateContact

我該如何做到這一點?

XML目前生產:

<?xml version=\"1.0\"?> 
<CreateContact xmlns:a="http://foo.co.uk/Contact" xmlns="http://foo.co.uk"> 
<a:contact> 
<a:Email>[email protected]</a:Email> 
<a:FirstName>Simon</a:FirstName> 
<a:LastName>Test</a:LastName> 
<a:Phone>09088408501</a:Phone> 
<a:Title>Mr</a:Title> 
</a:contact> 
</CreateContact> 

序列化功能:

public static void CreateContact(Contact contact) 
{ 
    string tmp = url; 
    string xml = ""; 
    string result = ""; 

    XmlDocument xd = new XmlDocument(); 

    var cc = new CreateContact(); 
    cc.contact = contact; 
    var xs = new XmlSerializer(cc.GetType()); 

    XmlSerializerNamespaces xsn = new XmlSerializerNamespaces(); 
    xsn.Add("a", "http://foo.co.uk/Contact"); 

    using (MemoryStream ms = new MemoryStream()) 
    { 
    xs.Serialize(ms, cc, xsn); 
    ms.Position = 0; 
    xd.Load(ms); 
    xml = xd.InnerXml; 
    } 

    using (WebClient web = new WebClient()) 
    { 
    web.Credentials = new NetworkCredential(username, password); 
    web.Headers.Add("Content-Type", "application/xml"); 
    try 
    { 
     result = web.UploadString(tmp, "POST", xml); 
    } 
    catch (WebException ex) 
    { 
    } 
    } 
} 

XML類構造:

[Serializable()] 
[XmlRoot(ElementName = "CreateContact", Namespace = "http://foo.co.uk")] 
public class CreateContact 
{ 
    [XmlElement(ElementName = "contact", Namespace = "http://foo.co.uk/Contact")] 
    public Contact contact { get; set; } 
} 

[DataContract(Name = "Contact", Namespace = "http://foo.co.uk/Contact")] 
[XmlType("a")] 
public class Contact 
{ 
    [XmlElement(ElementName = "Email", Namespace = "http://foo.co.uk/Contact")] 
    [DataMember(Name = "Email")] 
    public string Email { get; set; } 
    [XmlElement(ElementName = "FirstName", Namespace = "http://foo.co.uk/Contact")] 
    [DataMember(Name = "FirstName")] 
    public string Firstname { get; set; } 
    [XmlElement(ElementName = "LastName", Namespace = "http://foo.co.uk/Contact")] 
    [DataMember(Name = "LastName")] 
    public string Lastname { get; set; } 
    [XmlElement(ElementName = "Phone", Namespace = "http://foo.co.uk/Contact")] 
    [DataMember(Name = "Phone")] 
    public string Phone { get; set; } 
    [XmlElement(ElementName = "Title", Namespace = "http://foo.co.uk/Contact")] 
    [DataMember(Name = "Title")] 
    public string Title { get; set; } 
} 

XML期望:

<?xml version=\"1.0\"?> 
<CreateContact xmlns="http://foo.co.uk"> 
<contact xmlns:a="http://foo.co.uk/Contact"> 
<a:Email>[email protected]</a:Email> 
<a:FirstName>Simon</a:FirstName> 
<a:LastName>Test</a:LastName> 
<a:Phone>09088408501</a:Phone> 
<a:Title>Mr</a:Title> 
</contact> 
</CreateContact> 
+0

這兩者在語義上是等價的 - 是否有任何理由需要移動名稱空間聲明?我懷疑如果沒有一些手動序列化代碼或者在序列化後對XML進行後處理,這是不可能的。 –

+3

在「所需的」XML中,您的「contact」元素實際上位於「http:// foo.co.uk」命名空間中 - 是您真正想要的嗎? –

+0

@CharlesMager:他們略有不同 - 聯繫人元素位於OP所需XML中的不同名稱空間中,但我懷疑*這是一個錯誤... –

回答

3

正如在評論中提到,這種差異的原因是,contact應該在命名空間http://foo.co.uk,不http://foo.co.uk/Contact

順便說一句,一對夫婦的進一步意見:

  • 可能不需要DataMember屬性,除非你使用DataContractSerializer別的地方。
  • 此處大部分Xml*屬性是多餘的,可以通過從XmlRoot繼承來刪除或合併。
  • 如果你所需要的只是XML字符串,你最好將其序列化爲StringWriter而不是流,然後加載到DOM中以獲取文本(如果需要XML聲明,請參閱this question指定utf-8

所以,你會得到如下的XML:

var xsn = new XmlSerializerNamespaces(); 
xsn.Add("a", "http://foo.co.uk/Contact"); 

var xs = new XmlSerializer(typeof(CreateContact)); 

using (var stringWriter = new StringWriter()) 
{ 
    xs.Serialize(stringWriter, cc, xsn); 
    xml = stringWriter.ToString(); 
} 

隨着你的類定義爲:

[XmlRoot(ElementName = "CreateContact", Namespace = "http://foo.co.uk")] 
public class CreateContact 
{ 
    [XmlElement(ElementName = "contact")] 
    public Contact Contact { get; set; } 
} 

[XmlRoot("contact", Namespace = "http://foo.co.uk/Contact")] 
public class Contact 
{ 
    public string Email { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Phone { get; set; } 
    public string Title { get; set; } 
} 

完整示例請參見this fiddle

+0

更好的解釋,謝謝。我的示例中的數據成員是遺留的,必須在那裏,但我無法讓他們在POST情況下工作 – PurpleSmurph

相關問題