The XmlElement type is serialized using its XML contents. For example, using the following type.
<DataContract([Namespace] := "http://schemas.contoso.com")> _
Public Class MyDataContract
<DataMember()> _
Public myDataMember As XmlElement
Public Sub TestClass()
Dim xd As New XmlDocument()
myDataMember = xd.CreateElement("myElement")
myDataMember.InnerText = "myContents"
myDataMember.SetAttribute("myAttribute", "myValue")
End Sub
End Class
[DataContract(Namespace=@"http://schemas.contoso.com")]
public class MyDataContract
{
[DataMember]
public XmlElement myDataMember;
public void TestClass()
{
XmlDocument xd = new XmlDocument();
myDataMember = xd.CreateElement("myElement");
myDataMember.InnerText = "myContents";
myDataMember.SetAttribute
("myAttribute","myValue");
}
}
This is serialized to XML as follows:
<MyDataContract xmlns="http://schemas.contoso.com">
<myDataMember>
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
</myDataMember>
</MyDataContract>
Notice that a wrapper data member element <myDataMember> is still present. There is no way of removing this element in the data contract model. The serializers that handle this model (the DataContractSerializer and NetDataContractSerializer) may emit special attributes into this wrapper element. These attributes include the standard XML Schema Instance "nil" attribute (allowing the XmlElement to be null) and the "type" attribute (allowing XmlElement to be used polymorphically). Also, the following XML attributes are specific to WCF: "Id", "Ref", "Type" and "Assembly". These attributes may be emitted to support using the XmlElement with the object graph preservation mode enabled, or with the NetDataContractSerializer. (For more information about the object graph preservation mode, see Serialization and Deserialization.)
Arrays or collections of XmlElement are allowed and are handled as any other array or collection. That is, there is a wrapper element for the entire collection, and a separate wrapper element (similar to <myDataMember> in the preceding example) for each XmlElement in the array.
On deserialization, an XmlElement is created by the deserializer from the incoming XML. A valid parent XmlDocument is provided by the deserializer.
Make sure that the XML fragment that is deserialized to an XmlElement defines all prefixes that it uses and does not rely on any prefix definitions from ancestor elements. This is a concern only when using the DataContractSerializer to access XML from a different (non-DataContractSerializer) source.
When used with the DataContractSerializer, the XmlElement may be assigned polymorphically, but only to a data member of type Object. Even though it implements IEnumerable, an XmlElement cannot be used as a collection type and cannot be assigned to an IEnumerable data member. As with all polymorphic assignments, the DataContractSerializer emits the data contract name in the resulting XML – in this case, it is "XmlElement" in the "http://schemas.datacontract.org/2004/07/System.Xml" namespace.
With the NetDataContractSerializer, any valid polymorphic assignment of XmlElement (to Object or IEnumerable) is supported.
Do not attempt to use either of the serializers with types derived from XmlElement, whether they are assigned polymorphically or not.
Using arrays of XmlNode is very similar to using XmlElement. Using arrays of XmlNode gives you more flexibility than using XmlElement. You can write multiple elements inside the data member wrapping element. You can also inject content other than elements inside of the data member wrapping element, such as XML comments. Finally, you can put attributes into the wrapping data member element. All this can be achieved by populating the array of XmlNode with specific derived classes of XmlNode such as XmlAttribute, XmlElement or XmlComment. For example, using the following type.
<DataContract([Namespace] := "http://schemas.contoso.com")> _
Public Class MyDataContract
<DataMember()> _
Public myDataMember(3) As XmlNode
Public Sub TestClass()
Dim xd As New XmlDocument()
Dim xe As XmlElement = xd.CreateElement("myElement")
xe.InnerText = "myContents"
xe.SetAttribute("myAttribute", "myValue")
Dim atr As XmlAttribute = xe.Attributes(0)
Dim cmnt As XmlComment = xd.CreateComment("myComment")
myDataMember(0) = atr
myDataMember(1) = cmnt
myDataMember(2) = xe
myDataMember(3) = xe
End Sub
End Class
[DataContract(Namespace="http://schemas.contoso.com")]
public class MyDataContract
{
[DataMember]
public XmlNode[] myDataMember = new XmlNode[4];
public void TestClass()
{
XmlDocument xd = new XmlDocument();
XmlElement xe = xd.CreateElement("myElement");
xe.InnerText = "myContents";
xe.SetAttribute
("myAttribute","myValue");
XmlAttribute atr = xe.Attributes[0];
XmlComment cmnt = xd.CreateComment("myComment");
myDataMember[0] = atr;
myDataMember[1] = cmnt;
myDataMember[2] = xe;
myDataMember[3] = xe;
}
}
When serialized, the resulting XML is similar to the following code.
<MyDataContract xmlns="http://schemas.contoso.com">
<myDataMember myAttribute="myValue">
<!--myComment-->
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
</myDataMember>
</MyDataContract>
Note that the data member wrapper element <myDataMember> contains an attribute, a comment, and two elements. These are the four XmlNode instances that were serialized.
An array of XmlNode that results in invalid XML cannot be serialized. For example, an array of two XmlNode instances where the first one is an XmlElement and the second one is an XmlAttribute is invalid, because this sequence does not correspond to any valid XML instance (there is no place to attach the attribute to).
On deserialization of an array of XmlNode, nodes are created and populated with information from the incoming XML. A valid parent XmlDocument is provided by the deserializer. All nodes are deserialized, including any attributes on the wrapper data member element, but excluding the attributes placed there by the WCF serializers (such as the attributes used to indicate polymorphic assignment). The caveat about defining all namespace prefixes in the XML fragment applies to the deserialization of arrays of XmlNode just like it does to deserializing XmlElement.
When using the serializers with object graph preservation turned on, object equality is only preserved on the level of XmlNode arrays, not individual XmlNode instances.
Do not attempt to serialize an array of XmlNode where one or more of the nodes is set to null. It is permitted for the entire array member to be null, but not for any individual XmlNode contained in the array. If the entire array member is null, the wrapper data member element contains a special attribute that indicates that it is null. On deserialization, the entire array member also becomes null.
Only regular arrays of XmlNode are treated specially by the serializer. Data members declared as other collection types that contain XmlNode, or data members declared as arrays of types derived from XmlNode, are not treated specially. Thus, they are normally not serializable unless they also meet one of the other criteria for serializing.
Arrays or collections of arrays of XmlNode are allowed. There is a wrapper element for the entire collection, and a separate wrapper element (similar to <myDataMember> in the preceding example) for each array of XmlNode in the outer array or collection.
Populating a data member of type Array of Object or Array of IEnumerable with XmlNode instances does not result in the data member being treated as an Array of XmlNode instances. Each array member is serialized separately.
When used with the DataContractSerializer, arrays of XmlNode can be assigned polymorphically, but only to a data member of type Object. Even though it implements IEnumerable, an array of XmlNode cannot be used as a collection type and be assigned to an IEnumerable data member. As with all polymorphic assignments, the DataContractSerializer emits the data contract name in the resulting XML – in this case, it is "ArrayOfXmlNode" in the "http://schemas.datacontract.org/2004/07/System.Xml" namespace. When used with the NetDataContractSerializer, any valid assignment of an XmlNode array is supported.