Reputation: 6469
The Xml response I receive is as follows:
<response>
<item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
<name>some name</disc-name>
<description>some description</disc-desc>
</item>
<item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
<name>some name</disc-name>
<description>some description</disc-desc>
</item>
<otherValue>12.1</otherValue>
</response>
My class is decorated as such:
[XmlElement("item")]
public Item[] Items{get;set;}
[XmlElement("otherValue")
public string OtherValue{get;set;}
When I attempt to deserialize the above Xml to the class described, I receive an error of "Namespace prefix 'java' is not defined". Adding the "namespace" attribute to the class resolves the parsing error(however, the xml is then distorted from the original).
ie
[XmlElement(ElementName="item",Namespace="java")]
How should I be decorating a given property to match up with a new namespace? Or, how do I correctly define the namespace?
I'm not 100% on using a stock array for my enumerable section either, but I think the namespace issue takes precident at the moment. Any insight or thoughts are greatly appreciated!
UPDATE:
I think the question is better rephrased now that I've gone back and forth a bit:
How do you use an XmlElementAttribute(or other attribute) to have a class that can serialize into the item snippet above, including the xsi tags?
As for my particular problem, I've realized since the Xml response is out of my control, I don't need the xsi attributes to begin with. To workaround the serialization issue, I'm simply doing the following(XmlElement element contains the original document above):
foreach(XmlNode node in element)
node.Attributes.RemoveAll();
I'm only noting my personal workaround as this is not actually a solution.
Upvotes: 3
Views: 8031
Reputation: 1804
Unfortunately this is valid XML, and completely conforms to the XML Standard. It validates, it's correct and it's complete.
The problem you're having is in the deserialization, which is not a part of the XML Standard and is related to how .NET maps declared XML types to internal CLR types.
The xsi:type is a namespace reference and is intended to allow XML documents to substitute a derived type from another namespace for the declared type in the schema.
I know from my own experience that coders tend to react in shock that this sort of thing is even legal, much less correct XML. It basically hijacks your schema.
You do not need even need to include the foreign namespace in order for this to be considered correct.
(see this article for more ranting on this subject: http://norman.walsh.name/2004/01/29/trainwreck)
Now, as to how to handle your stated problem: deserialize this mess. 1) process the xml text and remove the xsi-types declaration and hope there are no fields declared that extend the base type. 2) declare a type that derives from your base type in the schema.
This looks like the following:
// note this "XmlIncludeAttribute" references the derived type.
// note that in .NET they are in the same namespace, but in XML they are in different namespaces.
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedType))]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://BaseNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://BaseNameSpace", IsNullable=true)]
public partial class MyBaseType : object
{
...
}
/// <remarks/>
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://DerivedNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://DerivedNameSpace", IsNullable=true)]
public partial class DerivedType: MyBaseType
{
...
}
This is only a rough outline, hopefully enough to get you started. Note that this is not an easy problem to solve progmatically because it's always possible for someone to feed you XML and it will validate but not deserialize properly.
Upvotes: 0
Reputation: 161831
You were right the first time. "java" is not a namespace. It's a namespace prefix. That's an abbreviation of the namespace, for use in the XML. Otherwise, the actual namespace would need to be repeated wherever you currently see "java:".
You can use List<Item>
instead of Item[]
.
Upvotes: 1