2016-08-03 75 views
1

我有一個使用XmlSerializer進行序列化的類。除了其他屬性之外,我還需要爲對象添加一大塊預構建的xml。我已經問過在這篇文章中如何處理xml的chuck:How to remove empty namespace attribute on manually added xml string when serializing object?如何序列化屬性上的屬性或跳過類層次結構

現在我需要向包含xml字符串的屬性添加一個屬性。我知道如何將一個屬性添加到類中,但不是屬性。如果我創建一個新的類來保存屬性,我會在輸出中獲得額外的層次結構。

這裏是我的簡化代碼:

public class Book 
{ 
    public string Title { get; set; } 

    public string Author { get; set; } 

    public XmlElement Extension { get; set; } 

    public Book() 
    { 
    } 

    public void AddExtension() 
    { 
     string xmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" + 
           "<SpecialHandling>Some Value</SpecialHandling>" + 
          "</AdditionalInfo>"; 

     this.Extension = GetElement(xmlString); 
    } 

    public static XmlElement GetElement(string xml) 
    { 
     XmlDocument doc = new XmlDocument(); 

     doc.LoadXml(xml); 

     return doc.DocumentElement; 
    } 
} 

static void Main(string[] args) 
{ 
    TestSerialization p = new TestSerialization(); 

    Book bookOne = new Book(); 

    bookOne.Title = "How to Fix Code"; 
    bookOne.Author = "Dee Bugger"; 

    bookOne.AddExtension(); 

    System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(Book), "http://www.somenamespace.com"); 

    using (var writer = new StreamWriter("C:\\BookReport.xml")) 
    using (var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings { Indent = true })) 
    { 
     serializer.Serialize(xmlWriter, bookOne); 
    } 
} 

它會生成以下的輸出:

<?xml version="1.0" encoding="utf-8"?> 
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.somenamespace.com"> 
    <Title>How to Fix Code</Title> 
    <Author>Dee Bugger</Author> 
    <Extension> 
    <AdditionalInfo xmlns="http://www.somenamespace.com"> 
     <SpecialHandling>Some Value</SpecialHandling> 
    </AdditionalInfo> 
    </Extension> 
</Book> 

現在我需要的屬性添加到擴展,使擴展輸出的樣子:

... 
<Extension Modifier="ABC"> 
    <AdditionalInfo xmlns="http://www.somenamespace.com"> 
     <SpecialHandling>Some Value</SpecialHandling> 
    </AdditionalInfo> 
</Extension> 

有沒有辦法改變Book類來做到這一點?我試圖創建一個擴展類來保存修改屬性和XML字符串的XmlElement但導致了額外的級別:

public class Extension 
{ 
    [XmlAttribute] 
    public string Modifier { get; set; } 

    [XmlElementAttribute("Extension")] 
    public XmlElement ExtensionAsElement { get; set; } 

    public Extension() 
    { 
    } 

    public Extension(XmlElement extensionAsElement) 
    { 
     this.Modifier = "ABC"; 

     this.ExtensionAsElement = extensionAsElement; 
    } 
} 

public class Book 
{ 
    public string Title { get; set; } 

    public string Author { get; set; } 

    [XmlElementAttribute("Extension")] 
    public Extension ExtensionObj { get; set; } 

    public Book() 
    { 
    } 

    public void AddExtension() 
    { 
     string xmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" + 
           "<SpecialHandling>Some Value</SpecialHandling>" + 
          "</AdditionalInfo>"; 

     this.ExtensionObj = new Extension(GetElement(xmlString)); 
    } 

    public static XmlElement GetElement(string xml) 
    { 
     XmlDocument doc = new XmlDocument(); 

     doc.LoadXml(xml); 

     return doc.DocumentElement; 
    } 
} 

<?xml version="1.0" encoding="utf-8"?> 
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.somenamespace.com"> 
    <Title>How to Fix Code</Title> 
    <Author>Dee Bugger</Author> 
    <Extension Modifier="ABC"> 
    <Extension> 
     <AdditionalInfo xmlns="http://www.somenamespace.com"> 
     <SpecialHandling>Some Value</SpecialHandling> 
     </AdditionalInfo> 
    </Extension> 
    </Extension> 
</Book> 

注:這是我的代碼過於簡化的例子,圖書類不是我的根。我只需要序列化,而不是反序列化。

回答

0

您可以使用[XmlAnyElement("Extension")]指定爲-到XML流作爲元素<Extension>本身,該名稱的元素,而不是作爲一個孩子Extension屬性應插入。完成後,您將能夠使用SetAttribute()GetAttribute()在元素本身上設置屬性。

因此您Book類成爲類似:

public class Book 
{ 
    public string Title { get; set; } 

    public string Author { get; set; } 

    [XmlAnyElement("Extension")] 
    public XmlElement Extension { get; set; } 

    public Book() 
    { 
     this.Extension = new XmlDocument().CreateElement("Extension"); 
    } 

    public Book AddExtension() 
    { 
     string innerXmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" + 
           "<SpecialHandling>Some Value</SpecialHandling>" + 
          "</AdditionalInfo>"; 
     if (Extension == null) 
      // Since Extension is marked with [XmlAnyElement("Extension")], its value must 
      // be an XmlElement named "Extension". Its InnerXml can be anything. 
      Extension = new XmlDocument().CreateElement("Extension"); 
     Extension.InnerXml = innerXmlString; 
     return this; 
    } 

    const string ModifierName = "Modifier"; 

    [XmlIgnore] 
    public string Modifier 
    { 
     get 
     { 
      if (Extension == null) 
       return null; 
      return Extension.GetAttribute(ModifierName); 
     } 
     set 
     { 
      if (Extension == null) 
       AddExtension(); 
      if (value == null) 
       Extension.RemoveAttribute(ModifierName); 
      else 
       Extension.SetAttribute(ModifierName, value); 
     } 
    } 
} 

和創建XML從以下方面:

var bookOne = new Book { Title = "How to Fix Code", Author = "Dee Bugger", Modifier = "AAA" } 
    .AddExtension(); 

產生的結果爲:

<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Title>How to Fix Code</Title> 
    <Author>Dee Bugger</Author> 
    <Extension Modifier="AAA"> 
     <AdditionalInfo xmlns="http://www.somenamespace.com"> 
      <SpecialHandling>Some Value</SpecialHandling> 
     </AdditionalInfo> 
    </Extension> 
</Book> 
+0

謝謝@ DBC。我只看到XmlAnyElement用於不同類型的數組。這非常有幫助,解決了我的問題! – sldorman

+0

對不起,我以爲我有:) – sldorman