2009-09-09 10 views
6

Mam problemy szeregowania sekcji CDATA przy użyciu C#serializacji XML - XmlCDataSection jak Serialization.XmlText

muszę właściwość obiektu XmlCDataSection do serializacji jako innerText elementu.

Wynik szukam to:

<Test value2="Another Test"> 
    <![CDATA[<p>hello world</p>]]> 
</Test> 

Aby to produkować, używam obiektu:

public class Test 
{ 
    [System.Xml.Serialization.XmlText()] 
    public XmlCDataSection value { get; set; } 

    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string value2 { get; set; } 
} 

Podczas korzystania z adnotacji xmlText na własność wartości jest następujący błąd rzucony.

System.InvalidOperationException: wystąpił błąd odzwierciedlających personelem na 'wartość'. ---> System.InvalidOperationException: Nie można przekształcić wartości członka w wartość typu System.Xml.XmlCDataSection. XmlAttribute/xmlText nie mogą być wykorzystywane do kodowania złożonych typów

Gdybym wykomentuj adnotacji, serializacji będzie działać, ale sekcja CDATA jest umieszczony w elemencie wartości co nie jest dobre dla co próbuję robić :

<Test value2="Another Test"> 
    <value><![CDATA[<p>hello world</p>]]></value> 
</Test> 

Czy ktoś może wskazać mi właściwy kierunek, aby to zadziałało.

Dzięki, Adam

+0

Co się dzieje, jeśli usunąć '[xmlText]'? –

Odpowiedz

5

Dzięki Richard, dopiero teraz miał okazję wrócić do tego. Myślę, że rozwiązałem problem, korzystając z Twojej sugestii. Stworzyłem obiekt CDataField, używając:

public class CDataField : IXmlSerializable 
    { 
     private string elementName; 
     private string elementValue; 

     public CDataField(string elementName, string elementValue) 
     { 
      this.elementName = elementName; 
      this.elementValue = elementValue; 
     } 

     public XmlSchema GetSchema() 
     { 
      return null; 
     } 

     public void WriteXml(XmlWriter w) 
     { 
      w.WriteStartElement(this.elementName); 
      w.WriteCData(this.elementValue); 
      w.WriteEndElement(); 
     } 

     public void ReadXml(XmlReader r) 
     {      
      throw new NotImplementedException("This method has not been implemented"); 
     } 
    } 
+0

rzuca 'A.CDataField nie może być serializowany, ponieważ nie ma błędu konstruktora parametrów – tchelidze

2

Sposób Test jest zdefiniowana, dane jest obiektem CDATA. Tak więc system serializacji próbuje zachować obiekt CData.

Ale chcesz serializować niektóre dane tekstowe jako sekcję CData.

Po pierwsze, typem Test.value powinien być łańcuch.

Następnie należy kontrolować sposób serializowania tego pola, ale nie ma żadnej wbudowanej metody ani atrybutu do kontrolowania, w jaki sposób łańcuchy są przekształcane do postaci szeregowej (jako łańcuch znaków, być może z encji dla zarezerwowanych znaków lub jako CDATA). (Ponieważ, z perspektywy informacji w formacie XML, wszystkie są takie same, nie jest to zaskakujące.)

Można oczywiście zaimplementować IXmlSerializable i po prostu kodować serializację typu Test, co daje pełną kontrolę.

0

Miałem ten sam problem co Adam. Jednak ta odpowiedź nie pomogła mi na 100% :), ale daje mi wskazówkę. Więc stworzyłem kod jak poniżej.Generuje XML tak:

<Actions> 
    <Action Type="reset"> 
     <![CDATA[ 
     <dbname>longcall</dbname> 
     <ontimeout> 
     <url>http://[IPPS_ADDRESS]/</url> 
     <timeout>10</timeout> 
     </ontimeout> 
     ]]> 
    </Action> 
    <Action Type="load"> 
     <![CDATA[ 
     <dbname>longcall</dbname> 
     ]]> 
    </Action> 
</Actions> 

Kod:

public class ActionsCDataField : IXmlSerializable 
{ 
    public List<Action> Actions { get; set; } 

    public ActionsCDataField() 
    { 
     Actions = new List<Action>(); 
    } 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void WriteXml(XmlWriter w) 
    { 
     foreach (var item in Actions) 
     { 
      w.WriteStartElement("Action"); 
      w.WriteAttributeString("Type", item.Type); 
      w.WriteCData(item.InnerText);     
      w.WriteEndElement(); 
      w.WriteString("\r\n"); 
     } 
    } 

    public void ReadXml(XmlReader r) 
    { 
     XmlDocument xDoc = new XmlDocument(); 
     xDoc.Load(r); 

     XmlNodeList nodes = xDoc.GetElementsByTagName("Action"); 
     if (nodes != null && nodes.Count > 0) 
     { 
      foreach (XmlElement node in nodes) 
      { 
       Action a = new Action(); 
       a.Type = node.GetAttribute("Type"); 
       a.InnerText = node.InnerXml; 
       if (a.InnerText != null && a.InnerText.StartsWith("<![CDATA[") && a.InnerText.EndsWith("]]>")) 
        a.InnerText = a.InnerText.Substring("<![CDATA[".Length, a.InnerText.Length - "<![CDATA[]]>".Length); 

       Actions.Add(a); 
      } 
     } 
    } 
} 

public class Action 
{ 
    public String Type { get; set; } 
    public String InnerText { get; set; } 
} 
1

Wystarczy znaleźć alternatywę z here:

 [XmlIgnore] 
      public string Content { get; set; } 

    [XmlText] 
      public XmlNode[] CDataContent 
      { 
       get 
       { 
        var dummy = new XmlDocument(); 
        return new XmlNode[] {dummy.CreateCDataSection(Content)}; 
       } 
       set 
       { 
        if (value == null) 
        { 
         Content = null; 
         return; 
        } 

        if (value.Length != 1) 
        { 
         throw new InvalidOperationException(
          String.Format(
           "Invalid array length {0}", value.Length)); 
        } 

        var node0 = value[0]; 
        var cdata = node0 as XmlCDataSection; 
        if (cdata == null) 
        { 
         throw new InvalidOperationException(
          String.Format(
           "Invalid node type {0}", node0.NodeType)); 
        } 

        Content = cdata.Data; 
       } 
      } 
     } 
Powiązane problemy