2008-11-20 14 views
7

Je voulais désérialiser un message XML contenant un élément qui peut être marqué nil="true" dans une classe avec une propriété de type int?. La seule façon de le faire fonctionner était d'écrire mon propre type NullableInt qui implémente IXmlSerializable. Y a-t-il une meilleure façon de le faire? J'ai écrit le problème complet et la façon dont j'ai résolu le problème on my blog.Est-ce que XmlSerializer peut être désérialisé en un Nullable <int>?

Répondre

5

Je pense que vous devez préfixer le nil = "true" avec un espace de noms pour que XmlSerializer désérialise à null.

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

Merci Phil, qui a travaillé un régal. Maintenant, j'ai juste besoin que le gars fournisse les messages pour ajouter l'espace de nom ... –

+0

Pas de soucis SCOA :-P Si vous ne pouvez pas changer le XML à la source (ça sonne comme vous le pouvez), vous pouvez le passer à travers une transformation XSLT pour ajouter l'espace de noms je pense ... –

+0

Oui JENP, il s'avère qu'il est difficile de le faire à la source car c'est une application Rails produisant le xml avec 'to_xml'. De plus, l'ajout de xsi: à l'attribut type fait que .NET recherche un type appelé 'array', qui n'existe pas. Donc à la fin ça va être plus facile de coller avec mon type 'NullableInt'. –

3

Mon correctif est de pré-traiter les nœuds, à corriger des « nuls » attributs:

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); 
} 

Je Coupler ceci avec une recherche récursive pour les noeuds enfant, de sorte que pour n'importe quel XmlNode (ou XmlDocument), je peux émettre un seul appel avant la désérialisation. Si vous souhaitez conserver la structure d'origine en mémoire non modifiée, utilisez un Clone() du XmlNode.

+0

Ça a très bien fonctionné pour moi, merci. Et explicitement pour la consommation de Rails. J'ai fait un léger ajustement pour vérifier les attributs non-null: XmlAttribute nilAttribute = null; if (@ this.Attributes! = Null) { nilAttribute = @ this.Attributes ["nil"]; } – Dylan

0

La manière exceptionnellement paresseuse de le faire. C'est fragile pour un certain nombre de raisons, mais mon XML est assez simple pour justifier une solution aussi rapide et sale.

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