Net XmlSerializer kullanarak bir dizgeyi CDATA olarak serileştirmek bir tür öznitelikle mümkün müdür?
Net XmlSerializer kullanarak bir dizgeyi CDATA olarak serileştirmek bir tür öznitelikle mümkün müdür?
Yanıtlar:
[XmlRoot("root")]
public class Sample1Xml
{
internal Sample1Xml()
{
}
[XmlElement("node")]
public NodeType Node { get; set; }
#region Nested type: NodeType
public class NodeType
{
[XmlAttribute("attr1")]
public string Attr1 { get; set; }
[XmlAttribute("attr2")]
public string Attr2 { get; set; }
[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));
}
Content = value[0].Value;
}
}
}
#endregion
}
[Serializable]
public class MyClass
{
public MyClass() { }
[XmlIgnore]
public string MyString { get; set; }
[XmlElement("MyString")]
public System.Xml.XmlCDataSection MyStringCDATA
{
get
{
return new System.Xml.XmlDocument().CreateCDataSection(MyString);
}
set
{
MyString = value.Value;
}
}
}
Kullanım:
MyClass mc = new MyClass();
mc.MyString = "<test>Hello World</test>";
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
StringWriter writer = new StringWriter();
serializer.Serialize(writer, mc);
Console.WriteLine(writer.ToString());
Çıktı:
<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyString><![CDATA[<test>Hello World</test>]]></MyString>
</MyClass>
XmlDocument().CreateCDataSection(MyString ?? String.Empty);
John Saunders tarafından gönderilen yönteme ek olarak, XmlCDataSection'ı doğrudan tür olarak kullanabilirsiniz , ancak neredeyse aynı şeyi ifade eder:
private string _message;
[XmlElement("CDataElement")]
public XmlCDataSection Message
{
get
{
XmlDocument doc = new XmlDocument();
return doc.CreateCDataSection( _message);
}
set
{
_message = value.Value;
}
}
Serileştirilecek sınıfta:
public CData Content { get; set; }
Ve CData sınıfı:
public class CData : IXmlSerializable
{
private string _value;
/// <summary>
/// Allow direct assignment from string:
/// CData cdata = "abc";
/// </summary>
/// <param name="value">The string being cast to CData.</param>
/// <returns>A CData object</returns>
public static implicit operator CData(string value)
{
return new CData(value);
}
/// <summary>
/// Allow direct assignment to string:
/// string str = cdata;
/// </summary>
/// <param name="cdata">The CData being cast to a string</param>
/// <returns>A string representation of the CData object</returns>
public static implicit operator string(CData cdata)
{
return cdata._value;
}
public CData() : this(string.Empty)
{
}
public CData(string value)
{
_value = value;
}
public override string ToString()
{
return _value;
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
_value = reader.ReadElementString();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteCData(_value);
}
}
Benzer bir ihtiyacım vardı ancak farklı bir çıktı formatı gerekiyordu - CDATA'yı içeren düğümde bir öznitelik istedim. Kendi çözümümü yaratmak için yukarıdaki çözümlerden biraz ilham aldım. Belki gelecekte birine yardımcı olur ...
public class EmbedScript
{
[XmlAttribute("type")]
public string Type { get; set; }
[XmlText]
public XmlNode[] Script { get; set; }
public EmbedScript(string type, string script)
{
Type = type;
Script = new XmlNode[] { new XmlDocument().CreateCDataSection(script) };
}
public EmbedScript()
{
}
}
Serileştirilecek üst nesnede aşağıdaki özelliğe sahibim:
[XmlArray("embedScripts")]
[XmlArrayItem("embedScript")]
public List<EmbedScript> EmbedScripts { get; set; }
Aşağıdaki çıktıyı alıyorum:
<embedScripts>
<embedScript type="Desktop Iframe">
<![CDATA[<div id="play_game"><iframe height="100%" src="http://www.myurl.com" width="100%"></iframe></div>]]>
</embedScript>
<embedScript type="JavaScript">
<![CDATA[]]>
</embedScript>
</embedScripts>
Benim durumumda karışık alanlar kullanıyorum, bazıları CDATA bazıları değil, en azından benim için aşağıdaki çözüm çalışıyor ....
Değer alanını her zaman okuyarak, ister CDATA ister sadece düz metin olsun, içeriği alıyorum.
[XmlElement("")]
public XmlCDataSection CDataValue {
get {
return new XmlDocument().CreateCDataSection(this.Value);
}
set {
this.Value = value.Value;
}
}
[XmlText]
public string Value;
Geç olsun güç olmasın.
Şerefe
Bu uygulama, kodladığınız dizede yuvalanmış CDATA işleme yeteneğine sahiptir (John Saunders orijinal cevabına göre).
Örneğin, aşağıdaki değişmez dizeyi CDATA'ya kodlamak istediğinizi varsayalım:
I am purposefully putting some <![CDATA[ cdata markers right ]]> in here!!
Ortaya çıkan çıktının şöyle görünmesini istersiniz:
<![CDATA[I am purposefully putting some <![CDATA[ cdata markers right ]]]]><![CDATA[> in here!!]]>
Aşağıdaki uygulama, dizi üzerinde döngü oluşturacak, örneklerini ...]]>...
bölünecek ...]]
ve >...
her biri için ayrı CDATA bölümleri oluşturacaktır.
[XmlRoot("root")]
public class Sample1Xml
{
internal Sample1Xml()
{
}
[XmlElement("node")]
public NodeType Node { get; set; }
#region Nested type: NodeType
public class NodeType
{
[XmlAttribute("attr1")]
public string Attr1 { get; set; }
[XmlAttribute("attr2")]
public string Attr2 { get; set; }
[XmlIgnore]
public string Content { get; set; }
[XmlText]
public XmlNode[] CDataContent
{
get
{
XmlDocument dummy = new XmlDocument();
List<XmlNode> xmlNodes = new List<XmlNode>();
int tokenCount = 0;
int prevSplit = 0;
for (int i = 0; i < Content.Length; i++)
{
char c = Content[i];
//If the current character is > and it was preceded by ]] (i.e. the last 3 characters were ]]>)
if (c == '>' && tokenCount >= 2)
{
//Put everything up to this point in a new CData Section
string thisSection = Content.Substring(prevSplit, i - prevSplit);
xmlNodes.Add(dummy.CreateCDataSection(thisSection));
prevSplit = i;
}
if (c == ']')
{
tokenCount++;
}
else
{
tokenCount = 0;
}
}
//Put the final part of the string into a CData section
string finalSection = Content.Substring(prevSplit, Content.Length - prevSplit);
xmlNodes.Add(dummy.CreateCDataSection(finalSection));
return xmlNodes.ToArray();
}
set
{
if (value == null)
{
Content = null;
return;
}
if (value.Length != 1)
{
throw new InvalidOperationException(
String.Format(
"Invalid array length {0}", value.Length));
}
Content = value[0].Value;
}
}
}
CDataContent
, yalnızca XML okuyorsanız ihtiyacınız olmamasıdır.XmlSerializer.Deserialize
sizin için otomatik olarak metne dönüştürecektir.