尽管元素值包含混合内容,但将元素值反序列化为字符串

时间:2012-01-04 17:01:51

标签: c# serialization xml-serialization deserialization xml-deserialization

假设这样的XML:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>
        <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
            <div><h1>content</h1></div>
        </html>
    </my:FieldComplex>
<my:Root>

和类似:

[Serializable]
[XmlType(AnonymousType = true, Namespace = "http://foo/bar")]
[XmlRoot(ElementName = "Root", Namespace = "http://foo/bar", IsNullable = false)]
public class MyRoot
{
    public string FieldBasic { get; set; }
    public string FieldComplex { get; set; }
}

如何将<my:FieldComplex>反序列化为FieldComplex内的字符串?它在内部找到HTML时失败。我想让它给我一个包含这个内容的字符串:

<html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
    <div><h1>content</h1></div>
</html>

如果我将FieldComplex声明为public object FieldComplex(即xsd:anyType),那么它有点可行,我可以使用XMLNode[]

但我需要FieldComplex为序列化类型字符串,因为序列化XML不包含HTML,它将如下:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>content</my:FieldComplex>
<my:Root>

FieldComplex声明为对象会在<my:FieldComplex>元素上插入这些属性:

 xmlns:q1="http://www.w3.org/2001/XMLSchema" p3:type="q1:string" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance

我不希望如此。我也不想使用不同的类进行序列化和反序列化。

那么,有可能吗?

长话短说,是否可以使用此课程:

public class MyRoot
{
    public string FieldBasic { get; set; }
    public string FielComplex { get; set; }
}

序列化为:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>content</my:FieldComplex>
<my:Root>

并从中反序列化:

<my:Root xmlns:my="http://foo/bar">
    <my:FieldBasic>content</my:FieldBasic>
    <my:FieldComplex>
        <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
            <div><h1>content</h1></div>
        </html>
    </my:FieldComplex>
<my:Root>

P.S。只是为了解释“为什么?”。我有一个班级女巫被序列化。然后,序列化的XML遍历应用程序中的多个节点,并最终返回,但如上所述进行了更改。这些层执行一些XML验证,并且在输入时具有额外的属性或元素使验证失败并停止流程。我想将返回XML映射到同一个类。内容只是字符串从它的角度来看,但序列化/反序列化当然不一样:(

2 个答案:

答案 0 :(得分:3)

您可以在XML中使用CDATA来指示内容是字符串文字:

<my:Root xmlns:my="http://foo/bar">
  <my:FieldBasic>content</my:FieldBasic>
  <my:FieldComplex>
    <![CDATA[
      <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
        <div><h1>content</h1></div>
      </html>
    ]]>
  </my:FieldComplex>
</my:Root>

答案 1 :(得分:3)

这还没有完成,因为我不记得你是否可以/如何将命名空间前缀添加到Xml序列化中的根元素。但是如果你在MyRoot类中实现IXmlSerializable接口,如下所示:

[XmlRoot("Root", Namespace="http://foo/bar")]
public class MyRoot : IXmlSerializable

然后自己编写XML序列化方法,如下所示:

        void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
        {
            reader.MoveToContent();
            var outerXml = reader.ReadOuterXml();
            XElement root = XElement.Parse(outerXml);

            this.FieldBasic = root.Elements(XName.Get("FieldBasic", "http://foo/bar")).First().Value;
            this.FieldComplex = root.Elements(XName.Get("FieldComplex", "http://foo/bar")).First().Elements().First().Value.Trim();
        }



        void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteRaw(String.Format("\r\n\t<my:FieldBasic>\r\n\t\t{0}\r\n\t</my:FieldBasic>", this.FieldBasic));
            writer.WriteRaw(String.Format("\r\n\t<my:FieldComplex>\r\n\t\t{0}\r\n\t</my:FieldComplex>\r\n", this.FieldComplex));
        }

(从GetSchema方法返回null)

这应该让你至少非常接近你所追求的目标。

您也可以找到这些链接。

IXmlSerializable

Namespaces