2008-11-20 7 views
7

Ich möchte eine XML-Nachricht deserialisieren, die ein Element enthält, das mit einer Eigenschaft des Typs int? als nil="true" markiert werden kann. Die einzige Möglichkeit, es zum Laufen zu bringen, war, meinen eigenen NullableInt Typ zu schreiben, der IXmlSerializable implementiert. Gibt es einen besseren Weg, es zu tun?Kann XmlSerializer in ein Nullable deserialize <int>?

Ich schrieb das vollständige Problem und die Art, wie ich es gelöst on my blog.

Antwort

5

Ich denke, Sie müssen die Präfix der Nil = "True" mit einem Namespace, damit XmlSerializer zu Null deserialised.

MSDN on xsi:nil

<?xml version="1.0" encoding="UTF-8"?> 
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="array"> 
    <entity> 
    <id xsi:type="integer">1</id> 
    <name>Foo</name> 
    <parent-id xsi:type="integer" xsi:nil="true"/> 
+0

Dank Phil, das funktionierte ein Vergnügen. Jetzt muss ich nur den Kerl bekommen, der die Nachrichten liefert, um den Namespace hinzuzufügen ... –

+0

Keine Sorgen SCOA :-P Wenn Sie das XML an der Quelle nicht ändern können (klingt wie Sie können), könnten Sie es durch eine XSLT-Transformation übergeben um den Namespace hinzuzufügen denke ich ... –

+0

Ja JENP, stellt sich heraus, es ist schwierig, es an der Quelle zu tun, da es eine Rails App ist, die das XML mit 'to_xml' erzeugt. Durch das Hinzufügen von xsi: zum type-Attribut wird .NET nach einem Typ namens 'array' gesucht, der nicht existiert. Am Ende wird es einfacher, mit meinem 'NullableInt' Typ zu bleiben. –

3

Meine Lösung ist, um die Knoten vorverarbeitet, Fixieren jeder „Null“ Attribute:

public static void FixNilAttributeName(this XmlNode @this) 
{ 
    XmlAttribute nilAttribute = @this.Attributes["nil"]; 
    if (nilAttribute == null) 
    { 
     return; 
    } 

    XmlAttribute newNil = @this.OwnerDocument.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance"); 
    newNil.Value = nilAttribute.Value; 
    @this.Attributes.Remove(nilAttribute); 
    @this.Attributes.Append(newNil); 
} 

ich dieses Paar mit einer rekursiven Suche nach untergeordneten Knoten, so dass für Bei jedem gegebenen XmlNode (oder XmlDocument) kann ich einen einzelnen Aufruf vor der Deserialisierung durchführen. Wenn Sie die ursprüngliche In-Memory-Struktur unverändert lassen möchten, arbeiten Sie mit Clone() des XmlNode.

+0

Das hat sehr gut für mich funktioniert, danke. Und explizit für den Rails-Verbrauch. Ich habe eine leichte Anpassung vorgenommen, um nach Nicht-Null-Attributen zu suchen: XmlAttribute nilAttribute = null; if (@ this.Attributes! = Null) { nilAttribute = @ this.Attributes ["nil"]; } – Dylan

0

Die außergewöhnlich faule Art, es zu tun. Es ist aus einer Reihe von Gründen fragil, aber mein XML ist einfach genug, um eine solche schnelle und dreckige Reparatur zu rechtfertigen.

xmlStr = Regex.Replace(xmlStr, "nil=\"true\"", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:nil=\"true\""); 
Verwandte Themen