I need to deserialize part of XML document into a model. The part in question looks more less like following:
<Root xmlns:c="Ala ma kota">
<!-- ... -->
<c:Histogram>
<Data Width="10" Height="20" />
</c:Histogram>
<!-- ... -->
</Root>
Deserialization is done by capturing the specific XmlNode
from XmlDocument
(in this case: c:Histogram
) and then using its XmlNode.OuterXml
as a source for the deserializer (I failed to find a way to deserialize object from an XmlNode
).
I have designed classes for this XML like following:
[XmlRoot("Histogram", Namespace = "Ala ma kota")]
public class Histogram
{
[XmlElement]
public Data Data { get; set; }
}
[XmlRoot]
public class Data
{
[XmlAttribute]
public int Width { get; set; }
[XmlAttribute]
public int Height { get; set; }
}
The deserialization runs without any exceptions, but the deserialized element misses Data (the property is null).
I hooked an handler for XmlSerializer.UnknownNode
event and indeed, the <Data ... />
is seen as an "Unknown node".
The only way I managed the deserialization to run was to add the namespace to the Data class:
[XmlRoot("Data", Namespace = "Ala ma kota")]
public class Data
// (...)
And also the XML (note the c:Data instead of Data):
<Root xmlns:c="Ala ma kota">
<!-- ... -->
<c:Histogram>
<c:Data Width="10" Height="20" />
</c:Histogram>
<!-- ... -->
</Root>
In this case the deserialization works like charm.
My questions:
First: what is the default namespace if the root node is defined with a named namespace? (I mean with prefix instead of simply xmlns="..."
) Can I explicitly define the default namespace, so that the inner model classes would be deserialized correctly?
<Root> // <- Default namespace is empty
<Data /> // <- Equal to default namespace
</Root>
<c:Root xmlns:c="Ala ma kota"> // <- Namespace is "Ala ma kota"
<Data /> // <- Namespace is ?
</c:Root>
Second: Is there a way to redefine model classes to avoid adding Namespace =
and c:
everywhere in C# and XML, respectively? I will have multiple model classes and adding those will be cumbersome. I'd like to avoid it if possible.
Third: Is there a way to rip off the namespace from the "inner-root" element so that the deserialization would work without problems?
So far I have worked around the problem by adding an artificial child element:
<Root xmlns:c="Ala ma kota">
<!-- ... -->
<c:Histogram>
<Config>
<Data Width="10" Height="20" />
</Config>
</c:Histogram>
<!-- ... -->
</Root>
Then instead of deserializing the "inner-root" element, I'm deserializing its first (and only) child.
I'm curious though if this problem can be solved without such workarounds.