42 votes

Sérialisation d'un objet sans espace de nom à l'aide de DataContractSerializer

Comment puis-je supprimer les espaces de noms XML à partir d'un objet de la représentation XML sérialisé à l'aide de DataContractSerializer?

Cet objet doit être sérialisé pour une très simple XML de sortie.

  • Dernière & la plus grande de les utiliser .Net 4 beta 2
  • L'objet n'aurez plus jamais besoin d'être désérialisé.
  • XML ne doit pas avoir tout xmlns:... de l'espace de noms refs
  • Tous les sous-types d'Exception et ISubObject doivent être pris en charge.
  • Il sera très difficile de changer l'objet d'origine.

Objet:

 [Serializable] 
 class MyObj
 {
     string str;
     Exception ex;
     ISubObject subobj;
 }

Besoin de sérialiser dans:

<xml>
  <str>...</str>
  <ex i:nil="true" />
  <subobj i:type="Abc">
     <AbcProp1>...</AbcProp1>
     <AbcProp2>...</AbcProp2>
  </subobj>
</xml>

J'ai utilisé ce code:

private static string ObjectToXmlString(object obj)
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer =
        new DataContractSerializer(
            obj.GetType(), null, Int32.MaxValue, false, false, null,
            new AllowAllContractResolver());

    var sb = new StringBuilder();
    using (var xw = XmlWriter.Create(sb, new XmlWriterSettings
    {
        OmitXmlDeclaration = true,
        NamespaceHandling = NamespaceHandling.OmitDuplicates,
        Indent = true
    }))
    {
        serializer.WriteObject(xw, obj);
        xw.Flush();

        return sb.ToString();
    }
}

À partir de cet article , j'ai adopté un DataContractResolver de sorte qu'aucun sous-types doivent être déclarés:

public class AllowAllContractResolver : DataContractResolver
{
    public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
    {
        if (!knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace))
        {
            var dictionary = new XmlDictionary();
            typeName = dictionary.Add(dataContractType.FullName);
            typeNamespace = dictionary.Add(dataContractType.Assembly.FullName);
        }
        return true;
    }

    public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
    {
        return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? Type.GetType(typeName + ", " + typeNamespace);
    }
}

47voto

marc_s Points 321990

Vous devez marquer les classes avec lesquelles vous souhaitez sérialiser:

 [DataContract(Namespace="")]
 

Dans ce cas, le sérialiseur de contrat de données n'utilisera aucun espace de nom pour vos objets sérialisés.

Marc

11voto

leat Points 466

Si vous êtes prêt à ignorer le comportement par défaut (comme je le fais actuellement), vous créez un XmlWriter personnalisé qui contourne l'écriture de l'espace de noms.

 using System.IO;
using System.Xml;

public class MyXmlTextWriter : XmlTextWriter
{
  public MyXmlTextWriter(Stream stream)
    : base(stream, null)
  {
  }

  public override void WriteStartElement(string prefix, string localName, string ns)
  {
    base.WriteStartElement(null, localName, "");
  }
}
 

Ensuite, dans votre client écrivain, quelque chose comme ce qui suit:

 var xmlDoc = new XmlDocument();
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var ms = new MemoryStream())
{
  using (var writer = new MyXmlTextWriter(ms))
  {
    serializer.WriteObject(writer, obj);
    writer.Flush();
    ms.Seek(0L, SeekOrigin.Begin);
    xmlDoc.Load(ms);
  }
}
 

Et la sortie contiendra des déclarations d'espace de noms, mais il n'y aura aucun usage en tant que tel:

 <TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Items xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <string>Item1</string>
    <string>Item2</string>
  </Items>
</TestObject>
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X