2010-03-04 5 views
1

J'ai un flux contenant xml dans le format suivant que je veux désérialiser en C# objetsPourquoi XmlReader ajoute-t-il un espace de nom uris à chaque élément?

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<OrganisationMetaData xmlns="urn:organisationMetaDataSchema"> 
    <Organisations> 
    <Organisation> 
     <Code>XXX</Code> 
     <Name>Yyyyyy</Name>... 

Je l'ai fait plein de fois avec des chaînes, mais avec le flux, il est bien vouloir l'espace de noms Annexer des attribuer à tous les éléments complexes. Si je supprime simplement l'attribut xmlns, et oublie de le valider par rapport à un schéma, il ajoute juste un attribut xmlns vide. Le problème que j'ai est que la méthode Deserialize dans XmlSerializer (?), Jette une erreur disant qu'il n'attend pas l'attribut. J'ai essayé de décorer la classe avec les attributs XmlRoot et XmlType mais cela n'a rien changé.

est ici la classe que je veux désérialiser dans

[XmlRoot(
    ElementName = "OrganisationMetaData", 
    Namespace = "urn:organisationMetaDataSchema")] 
public class OrganisationMetaData 
{ 
    public List<Organisation> Organisations { get; set; } 
} 

[XmlType(
    TypeName = "Organisation", 
    Namespace = "urn:organisationMetaDataSchema")] 
public class Organisation 
{ 
    public string Code {get; set;} 

    public string Name {get; set;} 
} 

Voici la méthode qui est utilisée pour faire le travail

public IList<Organisation> DeserializeOrganisations(Stream stream) 
    { 
     var serializer = new XmlSerializer(typeof(OrganisationMetaData)); 

     var mappingAssembly = //Resource in another assembly 

     var schemas = new XmlSchemaSet(); 
     schemas.Add(
      "urn:organisationMetaDataSchema", 
      XmlReader.Create(
       mappingAssembly.GetManifestResourceStream(
        // An xml schema 
        ) 
       ) 
      ); 
     var settings = new XmlReaderSettings() 
          { 
           ValidationType = ValidationType.Schema, 
           Schemas = schemas, 
           ValidationFlags = 
        XmlSchemaValidationFlags.ReportValidationWarnings 
          };    

     settings.ValidationEventHandler += settings_ValidationEventHandler; 
     var reader = XmlReader.Create(stream, settings); 

     var metaData= (OrganisationMetaData)serializer.Deserialize(reader); 
     return metaData.Organisations.ToList(); 
    } 

J'ai essayé cela en utilisant DataContractSerializer mais qui apporte ses propres oppotunities pour apprendre, donc si quelqu'un pouvait aider avec ce que je devrais mettre dans les attributs pour faire fonctionner XmlSerializer, ce serait génial.

Toute aide serait appréciée, merci.

Répondre

0

J'ai fini par changer le code à utiliser un contrat de données sérialiseur, il m'a donné des erreurs plus évidentes autour de l'espace de noms qui m'ont permis d'avoir un lecteur qui a validé le flux xml contre le schéma, puis rembobine le flux et l'utilise à nouveau dans un autre lecteur qui désérialise le XML. Lecture this question m'a alerté à un gotcha où les éléments xml doivent être dans l'ordre alphabétique. J'ai aussi trouvé que quand je désérialisais une propriété de ma classe qui était une énumération, j'ai besoin d'exiger que ce soit présent (il n'est pas nul après tout). Cela a alors causé une autre erreur où j'avais un nœud xml avec des valeurs omises (ok par mon schéma), mais le contrat de données s'attendait à ce que ceux-ci soient en séquence donc je devais le spécifier explicitement.

J'ai fini avec un membre de données attribut comme cette

[DataMember(
     Name = "MyEnumType", 
     EmitDefaultValue = false, 
     IsRequired = true, 
     Order = 3)] 
//Just assume I added this prop after my Code, and Name properties from above 

Merci à Marc pour prendre le temps de regarder cela.

1

La clé ici est que le [XmlRoot] ne peut être appliqué qu'à un type racine tel qu'une classe; Si vous utilisez un List<> en tant que root, cela ne fonctionnera pas - mais nous pouvons le faire avec [XmlElement]. J'utilise l'approche Stream (via Encoding.UTF8), mais notez que ce n'est pas vraiment le cœur de la question de l'OMI (le type de racine est):

[XmlRoot(Namespace="urn:organisationMetaDataSchema")] 
public class Organisations 
{ 
    private readonly List<Organisation> items = new List<Organisation>(); 
    [XmlElement("Organisation")] 
    public List<Organisation> Items { get { return items; } } 

} 
public class Organisation 
{ 
    public string Code { get; set; } 
    public string Name { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     string xml = @"<?xml version='1.0' encoding='utf-8' standalone='yes'?><Organisations xmlns='urn:organisationMetaDataSchema'><Organisation><Code>XXXX</Code><Name>YYYYYYYY</Name></Organisation></Organisations>"; 
     XmlSerializer ser = new XmlSerializer(typeof(Organisations)); 
     using (Stream input = new MemoryStream(Encoding.UTF8.GetBytes(xml))) 
     { 
      Organisations orgs = (Organisations)ser.Deserialize(input); 
     } 
    } 
} 
+0

Merci Marc, je vais avoir un peu de cerveau à présent. Mon fichier XML n'a pas les guillemets simples que votre chaîne a. Comment surmonteriez-vous cela, quelque chose d'aussi simple que Remplacer (...)? –

+0

J'ai essayé à peu près tout ce que je peux penser ici, donc après environ 8 heures, j'ai abandonné et je suis parti pour DataContractSerializer à la place, qui à l'est peut en dire un peu plus sur ce qu'il n'aime pas sur le xml . Merci pour votre aide Marc :) –

+0

@Mark - la citation unique n'a pas d'importance. Le code affiché doit désérialiser le fichier XML que vous avez cité. Pouvez-vous poster (ou envoyer un e-mail si vous le souhaitez) vos cours? Je suis sûr que je peux vous dire ce qui ne va pas ... –

Questions connexes