2010-11-14 17 views
2

Une question assez complexe, donc merci d'avance. Les deux fichiers xml qui suit à la fois valider contre les schémas donnés, mais en essayant de désérialiser en utilisant XmlSerializer de .Net que la première ne si correctement:Discordances dans la désérialisation de fichiers XML valides avec System.Xml.Serialization.XmlSerializer

<ex:iso_10303_28 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL" version="2.0" xmlns:ex="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common"> 
    <ex:iso_10303_28_header> 
    <ex:name>An Example</ex:name> 
    <ex:time_stamp>2010-11-12T13:04:00</ex:time_stamp> 
    <ex:author>John Hancock</ex:author> 
    <ex:organization>MegaCorp</ex:organization> 
    <ex:preprocessor_version>a preprocessor</ex:preprocessor_version> 
    <ex:originating_system>IfcXml dotNet Library</ex:originating_system> 
    <ex:authorization>none</ex:authorization> 
    <ex:documentation>documentation</ex:documentation> 
    </ex:iso_10303_28_header> 
    <ex:uos xsi:type="uos" id="uos_1" configuration="i-ifc2x3"> 
    <ex:Entity xsi:type="IfcOrganization" id="i1101"> 
     <Id xsi:nil="true" /> 
     <Name>MegaCorp</Name> 
     <Description xsi:nil="true" /> 
     <Roles xsi:nil="true" /> 
     <Addresses xsi:nil="true" /> 
    </ex:Entity> 
    <ex:Entity xsi:type="IfcCartesianPoint" id="i101"> 
     <Coordinates ex:itemType="ifc:IfcLengthMeasure" ex:cType="list"> 
     <IfcLengthMeasure>2500</IfcLengthMeasure> 
     <IfcLengthMeasure>0</IfcLengthMeasure> 
     <IfcLengthMeasure>0</IfcLengthMeasure> 
     </Coordinates> 
    </ex:Entity> 
    <ex:Entity xsi:type="IfcDirection" id="i102"> 
     <DirectionRatios ex:itemType="ex:double-wrapper" ex:cType="list"> 
     <ex:double-wrapper>0</ex:double-wrapper> 
     <ex:double-wrapper>1</ex:double-wrapper> 
     <ex:double-wrapper>0</ex:double-wrapper> 
     </DirectionRatios> 
    </ex:Entity> 
    </ex:uos> 
</ex:iso_10303_28> 

mais le second fichier n'a pas désérialiser correctement, dans le ci-dessous (iso_10303_28.uos as uos1).Items est désérialisé comme nul:

<?xml version="1.0" encoding="UTF-8"?> 
<ex:iso_10303_28 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:ex= 
    "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common" 
    xmlns="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL" 
    xsi:schemaLocation="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL 
    http://www.iai-tech.org/ifcXML/IFC2x3/FINAL/IFC2x3.xsd" 
    version="2.0"> 
    <ex:iso_10303_28_header> 
     <ex:name>An Example</ex:name> 
     <ex:time_stamp>2010-11-12T13:04:00</ex:time_stamp> 
     <ex:author>John Hancock</ex:author> 
     <ex:organization>MegaCorp</ex:organization> 
     <ex:preprocessor_version>a preprocessor</ex:preprocessor_version> 
     <ex:originating_system>IfcXml dotNet Library</ex:originating_system> 
     <ex:authorization>none</ex:authorization> 
     <ex:documentation>documentation</ex:documentation> 
    </ex:iso_10303_28_header> 
    <uos id="uos_1" description="" configuration="i-ifc2x3" edo=""> 
     <IfcOrganization id="i1101"> 
      <Name>MegaCorp</Name> 
     </IfcOrganization> 
     <IfcCartesianPoint id="i101"> 
      <Coordinates> 
       <IfcLengthMeasure>2500.0</IfcLengthMeasure> 
       <IfcLengthMeasure>0.0</IfcLengthMeasure> 
       <IfcLengthMeasure>0.0</IfcLengthMeasure> 
      </Coordinates> 
     </IfcCartesianPoint> 
     <IfcDirection id="i102"> 
      <DirectionRatios> 
       <ex:double-wrapper>0.</ex:double-wrapper> 
       <ex:double-wrapper>1.</ex:double-wrapper> 
       <ex:double-wrapper>0.</ex:double-wrapper> 
      </DirectionRatios> 
     </IfcDirection> 
    </uos> 
</ex:iso_10303_28> 

Mon désérialiseur est essentiellement:

iso_10303_28 deserialized = (iso_10303_28)serializer.Deserialize(reader); 

//using NUnit 
Assert.IsNotNull(deserialized); 
Assert.IsNotNull(deserialized.uos); 
uos1 uos1 = deserialized.uos as uos1; 
Assert.IsNotNull(uos1); 
Assert.IsNotNull(uos1.Items); //<---FAILS HERE 
Assert.AreEqual(3, uos1.Items.length); 

La classe UOS est:

[System.Xml.Serialization.XmlTypeAttribute(TypeName="uos", Namespace="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")] 
[System.Xml.Serialization.XmlRootAttribute("uos", Namespace="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", IsNullable=false)] 
public partial class uos1 : uos { 

    private Entity[] itemsField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute("Entity", Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
    public Entity[] Items { 
     get { 
      return this.itemsField; 
     } 
     set { 
      this.itemsField = value; 
     } 
    } 
} 

[System.Xml.Serialization.XmlIncludeAttribute(typeof(uos1))]  
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
public partial class uos { 

    private string idField; 

    private string[] expressField; 

    private string[] configurationField; 

    private string[] schemaLocationField; 

    private string edoField; 

    private string descriptionField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="ID")] 
    public string id { 
     get { 
      return this.idField; 
     } 
     set { 
      this.idField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")] 
    public string[] express { 
     get { 
      return this.expressField; 
     } 
     set { 
      this.expressField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")] 
    public string[] configuration { 
     get { 
      return this.configurationField; 
     } 
     set { 
      this.configurationField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")] 
    public string[] schemaLocation { 
     get { 
      return this.schemaLocationField; 
     } 
     set { 
      this.schemaLocationField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")] 
    public string edo { 
     get { 
      return this.edoField; 
     } 
     set { 
      this.edoField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string description { 
     get { 
      return this.descriptionField; 
     } 
     set { 
      this.descriptionField = value; 
     } 
    } 
} 

La classe pour iso_10303_28 est la suivante:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common", IsNullable=false)] 
public partial class iso_10303_28 { 

    private iso_10303_28_header iso_10303_28_headerField; 

    private uos uosField; 

    private string versionField; 

    /// <remarks/> 
    public iso_10303_28_header iso_10303_28_header { 
     get { 
      return this.iso_10303_28_headerField; 
     } 
     set { 
      this.iso_10303_28_headerField = value; 
     } 
    } 

    public enum uosChoice 
    { 
     [XmlEnum("http://www.iai-tech.org/ifcXML/IFC2x3/FINAL:uos")] 
     uos1, 
     [XmlEnum("urn:iso.org:standard:10303:part(28):version(2):xmlschema:common:uos")] 
     uos 
    } 

    [XmlIgnore()] 
    public uosChoice uosChoiceField; 

    [XmlChoiceIdentifier("uosChoiceField")] 
    [XmlElement(ElementName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(uos1))] 
    [XmlElement(ElementName = "uos", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
    public uos uos { 
     get { 
      return this.uosField; 
     } 
     set { 
      this.uosField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string version { 
     get { 
      return this.versionField; 
     } 
     set { 
      this.versionField = value; 
     } 
    } 
} 

Quelqu'un at-il rencontré ce problème avant? Y a-t-il une raison à cela? Ai-je manqué quelque chose? est-il un correctif ou une solution de contournement? Comme les schémas et le reste du code sont assez volumineux, essayer de les simplifier au minimum a causé plus de problèmes (voir this question). Je ne les ai pas collés ici. Cependant, si nécessaire, les schémas, les tests unitaires et la source de ce problème peuvent être trouvés à http://code.google.com/p/ifc-dotnet/

Répondre

3

Les deux fichiers XML ne sont pas identiques, dans fichier-1 uso est qualifié sous ex, donc il est sous "urn: iso .org: standard: 10303: partie (28): version (2): xmlschema: commun "namespace, alors qu'en second il n'est pas et est sous l'espace de noms par défaut. Dans la classe 'iso_10303_28' propriété de type uos, XmlSerializer attendra des éléments avec le nom 'uos' (par défaut) sous le même espace de noms que celui de iso_10303_28 et 'xsi: type' 'uos' comme décrit par classe 'uos' - sous la même - "urn: iso.org: standard: 10303: partie (28): version (2): xmlschema: commun" namespace. Donc, cela explique pourquoi vous obtenez null dans le second xml. Si vous avez aucun contrôle sur xml - et si vous êtes en mesure de désérialiser l'un d'eux, essayez de suivre

  1. type UOS n'a aucune connaissance du type uos1 sauf indication par attribut XmlInclude. Je pense que vous avez ajouté un attribut XmlInclude sur la classe uos pour inclure uos1 en tant que type connu. Si ce n'est pas le cas, le sérialiseur ne désérialise pas le premier fichier. Sinon - vous devriez le faire comme ci-dessous

    [System.Xml.Serialization.XmlInclude (typeof (uos1))] [System.Xml.Serialization.XmlTypeAttribute (namespace = « urn: iso.org: standard: 10303: partie (28): Version (2): xmlschema: commune ")] public partial class UOS {

    } 
    
  2. Vous pouvez ajouter des attributs pour XmlElement iso_10303_28.uos de propriété à accepter les noms sous espace de noms soit - et utilisez un identifiant de choix ou utilisez 'uos []' comme type au lieu de 'uos'. Avec identifiant de choix - il peut être fait comme

[System.Xml.Serialization.XmlRootAttribute (namespace = « urn: iso.org: Norme: 10303: partie (28): Version (2): xmlschema: commune », IsNullable = false)] public partial class iso_10303_28 { UOS privés uosField;

public enum uosChoice 
    { 
     [XmlEnum("http://www.iai-tech.org/ifcXML/IFC2x3/FINAL:uos")] 
     uos, 
     [XmlEnum("urn:iso.org:standard:10303:part(28):version(2):xmlschema:common:uos")] 
     uos1 
    } 

    [XmlIgnore] 
    public uosChoice uosChoiceField; 

    [XmlChoiceIdentifier("uosChoiceField")] 
    [XmlElement(ElementName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(uos1))] 
    [XmlElement(ElementName = "uos", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
    public uos uos 
    { 
     get 
     { 
      return this.uosField; 
     } 
     set 
     { 
      this.uosField = value; 
     } 
    } 


} 

EDIT: Pour analyser Articles correctement, modifier uos1 comme celui-ci

[System.Xml.Serialization.XmlTypeAttribute(TypeName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")] 
    [System.Xml.Serialization.XmlRootAttribute("uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", IsNullable = false)] 
    public partial class uos1 : uos 
    { 
     private Entity[] itemsField; 

     /// <remarks/> 
     [XmlElement(ElementName = "Entity", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common", Type = typeof(Entity))] 
     [XmlElement(ElementName = "IfcOrganization", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcOrganization))] 
     [XmlElement(ElementName = "IfcCartesianPoint", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcCartesianPoint))] 
     [XmlElement(ElementName = "IfcDirection", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcDirection))] 
     public Entity[] Items 
     { 
      get 
      { 
       return this.itemsField; 
      } 
      set 
      { 
       this.itemsField = value; 
      } 
     } 

    } 

[System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcOrganization", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")] 
    public class IfcOrganization : Entity 
    { 

    } 

    [System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcCartesianPoint", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")] 
    public class IfcCartesianPoint : Entity 
    { 

    } 

    [System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcDirection", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")] 
    public class IfcDirection : Entity 
    { 

    } 

    [XmlInclude(typeof(IfcOrganization))] 
    [XmlInclude(typeof(IfcCartesianPoint))] 
    [XmlInclude(typeof(IfcDirection))] 
    [System.Xml.Serialization.XmlTypeAttribute(TypeName = "Entity", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 
    public class Entity 
    { 

    } 
+0

sur l'application # 2, je suis arrivé deux ou trois erreurs. '[XmlChoiceIdentifier ("ignoré")]' doit être '[XmlChoiceIdentifier ("uosChoice")]' et 'uosChoice publique uosChoiceField' devrait avoir l'attribut '[XmlIgnore()]' dessus –

+0

Faire ces changements comme indiqué dans le commentaire ci-dessus Révision 7 à code.google.com/p/ifc-dotnet/source/checkout), le test de désérialisation désérialise maintenant uos, il n'est donc pas nul. Malheureusement, il ne peut pas lancer uos à uos1, ce qui signifie que tous les uos1.Items importants ne sont toujours pas accessibles. :( –

+0

Désolé, [XmlChoiceIdentifier ("ignored")] doit être remplacé par [XmlChoiceIdentifier ("uosChoice")] comme indiqué – mho