使用.NET XML序列化在其他元素中包装序列化属性

时间:2009-08-04 10:07:02

标签: c# .net xml visual-studio-2008 xml-serialization

我正在使用C#+ VSTS2008 + .Net 3.0来进行XML序列化。代码工作正常。下面是我的代码和当前序列化的XML结果。

现在我想在输出XML文件中添加两个额外的图层。这是我期望的XML结果。有什么简单的方法吗?我不确定NestingLevel是否可以帮助这样做。我想找到一种不会改变MyClass和MyObject结构的简单方法。

预期的XML序列化结果,

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MyObjectProperty>
    <AdditionalLayer1>
      <AdditionalLayer2>
        <ObjectName>Foo</ObjectName>
      </AdditionalLayer1>
    </AdditionalLayer2>
  </MyObjectProperty>
</MyClass>

当前XML序列化结果,

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MyObjectProperty>
    <ObjectName>Foo</ObjectName>
  </MyObjectProperty>
</MyClass>

我目前的代码,

public class MyClass
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

public class Program
{
    static void Main(string[] args)
    {
        XmlSerializer s = new XmlSerializer(typeof(MyClass));
        FileStream fs = new FileStream("foo.xml", FileMode.Create);
        MyClass instance = new MyClass();
        instance.MyObjectProperty = new MyObject();
        instance.MyObjectProperty.ObjectName = "Foo";
        s.Serialize(fs, instance);

        return;
    }
}

5 个答案:

答案 0 :(得分:5)

  

我想找到一种不会改变MyClass和MyObject结构的简单方法。

坦率地说,这不会发生。 XmlSerializer(简单地使用时)遵循类/成员的结构。因此,您无法在不更改结构的情况下添加额外的图层。

当以定制方式(IXmlSerializable)使用时,您可以肯定的一点是它并不简单......这不是一个有趣的界面来实现。

我的建议:介绍一个模仿所需格式的DTO,并在序列化之前填充它。

答案 1 :(得分:4)

为什么还需要这两个额外的图层?

这是业务需求,您应该将这两个对象添加到对象模型中:

public class MyClass
{
    public AdditionalLayer1 AdditionalLayer1;
}
public class AdditionalLayer1
{
    public AdditionalLayer2 AdditionalLayer2;
}
public class AdditionalLayer2
{
    public MyObject MyObjectProperty;
}
public class MyObject
{
    public string ObjectName;
}

如果纯粹是因为某些兼容性要求,你可以做上面的事情,或者在MyClass上实现IXmlSerializable:

public class MyClass : IXmlSerializable
{
    public MyObject MyObjectProperty;

    public void WriteXml (XmlWriter writer)
    {
        //open the two layers
        //serialize MyObject
        //close the two layers
    }

    public void ReadXml (XmlReader reader)
    {
        //read all the layers back, etc
    }

    public XmlSchema GetSchema()
    {
        return(null);
    }

}

答案 2 :(得分:2)

您可以在序列化后使用XSL进行转换并添加“缺失”标记。

答案 3 :(得分:1)

我建议序列化为MemoryStream而不是FileStream,然后将XML加载到XmlDocument,然后使用该类的方法插入所需的额外节点。之后,您可以将其保存。

答案 4 :(得分:0)

我最近才这样做,并没有发现在所有困难或复杂的情况下覆盖IXmlSerializable接口。序列化/反序列化正常但对于包含子类的类,您需要在IXmlSerializable派生的额外标记中包含该类:

class ContainingClass : IXmlSerializable
{
 ...

#region IXmlSerializable Members

public XmlSchema GetSchema()
{
  return null;
}

public void ReadXml(XmlReader reader)
{
  **reader.ReadStartElement("Equipment");**

  XmlSerializer ser = new XmlSerializer(typeof(Host));

  while (reader.NodeType != XmlNodeType.EndElement)
  {
    Host newHost = new Host();
    newHost.Name = (string) ser.Deserialize(reader);
    _hosts.Add(newHost);

    reader.Read();
  }

  // Read the node to its end.
  // Next call of the reader methods will crash if not called.
  **reader.ReadEndElement(); // "Equipment"**
}

public void WriteXml(XmlWriter writer)
{
  XmlSerializer ser = new XmlSerializer(typeof(Host));
  **writer.WriteStartElement("Equipment");**
  foreach (Host host in this._hosts)
  {
    ser.Serialize(writer, host);
  }
  **writer.WriteEndElement();**
}

#endregion

我在这里所做的就是包装低级对象的de / serialization。在这里,我在这个类的集合中的所有主机周围包装了一个额外的标签“Equipment”。只要您关闭每个标签,就可以在此处添加任意数量的标签。

注意:Bold显示为**文本** - 只是确保你摆脱双星号:)