9
votes

Désérialiser xml sans espaces de noms mais dans une classe attend des espaces de noms

Dupliquer:
omettant tous les espaces de noms XML lors de la sérialisation d'un objet? Pas la même chose .. Je veux de l'autre côté: désériorialiser!


J'ai une classe C # comme ci-dessous: xxx

J'utilise cette classe pour sérialiser / désérialiser des fichiers XML par la demande de l'utilisateur. Mais j'ai un problème: la définition des espaces de noms a été ajoutée sur la nouvelle version de ce logiciel. Le XML est toujours le même, n'ayant que l'ajout de la définition des espaces de noms.

par exemple, par exemple, la dernière version ... xxx

et nouvelle version ... xxx

J'ai besoin de charger des fichiers XML avec et sans ces espaces de noms. J'ai beaucoup de classes imbriquées et chacun a sa propre définition des espaces de noms.

Je voudrais utiliser les mêmes classes pour les deux XML, avec et sans espaces de noms.

J'ai essayé de créer un XMLTExtreader et écraser la méthode de type NAMESPACEURI, mais je reçois toujours une exception sans aucune information. Je pense que .NET moteur essaie de forcer la définition de l'espace de noms de classe contre le XML.


3 commentaires

Salut, votre requête est-elle résolue?


Arijit, j'ai résolu-le en utilisant une approche différente. Malheureusement, il n'y a aucun moyen de faire ce que je voulais comme je le souhaite (en utilisant moins de code que possible). J'ai donc utilisé XMLTexTreader pour certains webservices et sur d'autres, j'ai sérialisé l'ensemble XML dans une chaîne et supprimé les espaces de noms inutilisés à l'aide de String.replace. Pas la meilleure chose que jamais, mais cela s'est avéré être bon aussi.


Merci pour la réponse, bien, mon problème se ressemble, la réponse donnée ci-dessous ne fonctionne pas, je suppose. Pouvez-vous montrer comment vous l'avez fait? C'est 4 ans pourquoi Microsoft n'y avait-il pas pensé?


4 Réponses :


-1
votes

Vous devez implémenter ixmlSerializable pour améliorer votre sérialisation personnalisée.


1 commentaires

J'ai beaucoup de classes imbriquées. Serait terrible de le mettre en œuvre sur chacune de ces classes juste pour supprimer les espaces de noms !!!! Je devrais ajouter un xmlschemaprovider pour chaque classe, renvoyer différents schémas en fonction de la version. N'y a-t-il pas un moyen plus facile de faire désérialiser? Tout comme l'ajout d'une chaîne d'espace de noms vide à la fonction Serialize?



1
votes

Vous pouvez lire le fichier en tant que texte en tant que texte, supprimer le texte de l'espace de noms incriminé, puis désérialisez-le.

Vous devrez peut-être écrire le "bon" texte dans un flux [mémoire / chaîne / corder / etc.] de sorte que le désériialize de XMLSerializer puisse être appelé.


1 commentaires

Oui ... Cela semble être le "meilleur" chemin. TKS!



9
votes

J'avais rencontré un défi similaire avec une classe de proxy. Pour des raisons que je n'entrerai pas dans, j'avais besoin de sérialiser manuellement la classe à l'aide du XMLSerializer sur Web Server et de désérialiser sur le client. Je n'ai pas pu trouver une solution élégante en ligne, alors je viens d'éviter le problème en retirant le xmltypeattribute de la classe de proxy manuellement après que je l'ai généré automatiquement dans Visual Studio.

Je revenais revenir pour voir s'il y avait un moyen pour obtenir l'espace de noms d'entraînement. Voici comment je l'ai acquis sans la nécessité de modifier les classes générées automatiquement. J'ai fini par utiliser un XMLTExtreader pour renvoyer l'espace de noms souhaité sur les nœuds correspondant à un nom de propriété. Il y a place à l'amélioration, mais j'espère que cela aide quelqu'un. P>

class Program
{
    static void Main(string[] args)
    {
        //create list to serialize
        Person personA = new Person() { Name = "Bob", Age = 10, StartDate = DateTime.Parse("1/1/1960"), Money = 123456m };
        List<Person> listA = new List<Person>();
        for (int i = 0; i < 10; i++)
        {
            listA.Add(personA);
        }

        //serialize list to file
        XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
        XmlTextWriter writer = new XmlTextWriter("Test.xml", Encoding.UTF8);
        serializer.Serialize(writer, listA);
        writer.Close();

        //deserialize list from file
        serializer = new XmlSerializer(typeof(List<ProxysNamespace.Person>));
        List<ProxysNamespace.Person> listB;
        using (FileStream file = new FileStream("Test.xml", FileMode.Open))
        {
            //configure proxy reader
            XmlSoapProxyReader reader = new XmlSoapProxyReader(file);
            reader.ProxyNamespace = "http://myappns.com/";      //the namespace of the XmlTypeAttribute 
            reader.ProxyType = typeof(ProxysNamespace.Person); //the type with the XmlTypeAttribute

            //deserialize
            listB = (List<ProxysNamespace.Person>)serializer.Deserialize(reader);
        }

        //display list
        foreach (ProxysNamespace.Person p in listB)
        {
            Console.WriteLine(p.ToString());
        }

        Console.ReadLine();
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime StartDate { get; set; }
    public decimal Money { get; set; }
}

namespace ProxysNamespace
{
    [XmlTypeAttribute(Namespace = "http://myappns.com/")]
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime Birthday { get; set; }
        public decimal Money { get; set; }

        public override string ToString()
        {
            return string.Format("{0}:{1},{2:d}:{3:c2}", Name, Age, Birthday, Money);
        }
    }
}

public class XmlSoapProxyReader : XmlTextReader
{
    List<object> propNames;
    public XmlSoapProxyReader(Stream input)
        : base(input)
    {
        propNames = new List<object>();
    }

    public string ProxyNamespace { get; set; }

    private Type proxyType;
    public Type ProxyType
    {
        get { return proxyType; }
        set
        {
            proxyType = value;
            PropertyInfo[] properties = proxyType.GetProperties();
            foreach (PropertyInfo p in properties)
            {
                propNames.Add(p.Name);
            }
        }
    }

    public override string NamespaceURI
    {
        get
        {
            object localname = LocalName;
            if (propNames.Contains(localname))
                return ProxyNamespace;
            else
                return string.Empty;
        }
    }
}


1 commentaires

Salut verre, je suis presque dans un problème similaire, besoin d'aide



8
votes

Afin de désérialiser XML sans espace de noms Ajouter un attribut xmlroot à la classe qui représente le haut de votre hiérarchie: xxx pré>

dans mon exemple, le XML n'a pas d'espace de noms et commence comme P>

using (FileStream stream = File.Open(filePath, FileMode.Open))
{
   XmlReader reader = new XmlTextReader(stream);                
   XmlSerializer serializer = new XmlSerializer(typeof(Plugins));
   var plugins = (Plugins)serializer.Deserialize(reader);
}


0 commentaires