2011-07-26 19 views
5

Mam problem z deserializacji moich plików xml. Podejmijmy, że mamy plik xml i klasę, której używamy do deserializacji.XmlSerializer. Pomiń xml nieznany węzeł

Na przykład:

xml -

<dataStore> 
    <name>newDataStore1</name> 
    <description>sdffasdfasdf</description> 
    <type>Shapefile</type> 
    <enabled>false</enabled> 
    <workspace> 
    <name>newTestWorkspace</name> 
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="ht 
tp://192.168.6.71:8080/geoserver/rest/workspaces/newTestWorkspace.xml" type="app 
lication/xml"/> 
    </workspace> 
    <connectionParameters> 
    <entry key="memory mapped buffer">false</entry> 
    <entry key="create spatial index">true</entry> 
    <entry key="charset">ISO-8859-1</entry> 
    <entry key="filetype">shapefile</entry> 
    <entry key="cache and reuse memory maps">true</entry> 
    <entry key="url">file:data/shapefiles/states.shp</entry> 
    <entry key="namespace">http://www.opengeospatial.net/cite</entry> 
    </connectionParameters> 
    <__default>false</__default> 
    <featureTypes> 
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="ht 
tp://192.168.6.71:8080/geoserver/rest/workspaces/newTestWorkspace/datastores/new 
DataStore1/featuretypes.xml" type="application/xml"/> 
    </featureTypes> 
</dataStore> 

Klasa

namespace GeoServerApiTester 
{ 


    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlRootAttribute("dataStore", Namespace="", IsNullable=false)] 
    public partial class DataStore 
    { 

     private string nameField; 

     private string typeField; 

     private bool enabledField; 

     private WorkSpacePreview workspaceField; 

     private ConnectionParametersStorageEntryCollection connectionParametersField; 

     private string @__defaultField; 

     private LinkCollection featureTypesField; 

     /// <remarks/> 
     [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0, ElementName="name")] 
     public string Name 
     { 
      get 
      { 
       return this.nameField; 
      } 
      set 
      { 
       this.nameField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1, ElementName="type")] 
     public string Type 
     { 
      get 
      { 
       return this.typeField; 
      } 
      set 
      { 
       this.typeField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2, ElementName="enabled")] 
     public bool Enabled 
     { 
      get 
      { 
       return this.enabledField; 
      } 
      set 
      { 
       this.enabledField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlElementAttribute(Order=3, ElementName="workspace")] 
     public WorkSpacePreview Workspace 
     { 
      get 
      { 
       return this.workspaceField; 
      } 
      set 
      { 
       this.workspaceField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlArrayAttribute(Order=4, ElementName="connectionParameters")] 
     [System.Xml.Serialization.XmlArrayItemAttribute("entry", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)] 
     public ConnectionParametersStorageEntryCollection ConnectionParameters 
     { 
      get 
      { 
       return this.connectionParametersField; 
      } 
      set 
      { 
       this.connectionParametersField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)] 
     public string @__default 
     { 
      get 
      { 
       return [email protected]__defaultField; 
      } 
      set 
      { 
       [email protected]__defaultField = value; 
      } 
     } 

     /// <remarks/> 
     [System.Xml.Serialization.XmlArrayAttribute(Order=6, ElementName="featureTypes")] 
     [System.Xml.Serialization.XmlArrayItemAttribute("link", Namespace="http://www.w3.org/2005/Atom", IsNullable=false)] 
     public LinkCollection FeatureTypes 
     { 
      get 
      { 
       return this.featureTypesField; 
      } 
      set 
      { 
       this.featureTypesField = value; 
      } 
     } 

     public virtual bool ShouldSerializeConnectionParameters() 
     { 
      return ((this.ConnectionParameters != null) 
         && (this.ConnectionParameters.Count > 0)); 
     } 

     public virtual bool ShouldSerializeFeatureTypes() 
     { 
      return ((this.FeatureTypes != null) 
         && (this.FeatureTypes.Count > 0)); 
     } 
    } 
} 

Można zobaczyć, że klasa nie zawiera opis pola.

<dataStore> 
    <name>newDataStore1</name> 
    <enabled>false</enabled> 
</dataStore> 

Widać, że wszystkie elementy po opisie nie zostały przekształcone do postaci szeregowej.

Gdy program dostaje treść xml, a ten xml zawiera element, którego nie ma w klasie, wszystkie elementy po tym elemencie nie będą desirializowane.

Jak mogę pominąć nieznanego elementu podczas deserializacji i uzyskać coś takiego:

<dataStore> 
    <name>newDataStore1</name> 

    <type>Shapefile</type> 
    <enabled>false</enabled> 
    <workspace> 
    <name>newTestWorkspace</name> 
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="ht 
tp://192.168.6.71:8080/geoserver/rest/workspaces/newTestWorkspace.xml" type="app 
lication/xml"/> 
    </workspace> 
    <connectionParameters> 
    <entry key="memory mapped buffer">false</entry> 
    <entry key="create spatial index">true</entry> 
    <entry key="charset">ISO-8859-1</entry> 
    <entry key="filetype">shapefile</entry> 
    <entry key="cache and reuse memory maps">true</entry> 
    <entry key="url">file:data/shapefiles/states.shp</entry> 
    <entry key="namespace">http://www.opengeospatial.net/cite</entry> 
    </connectionParameters> 
    <__default>false</__default> 
    <featureTypes> 
    <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="ht 
tp://192.168.6.71:8080/geoserver/rest/workspaces/newTestWorkspace/datastores/new 
DataStore1/featuretypes.xml" type="application/xml"/> 
    </featureTypes> 
</dataStore> 

usunąć tylko elementu

Odpowiedz

9

Domyślnie XmlSerializer ignoruje nieznanych węzłów (tak pierwiastków, jak również). Teraz, gdy użyjesz właściwości Order tak, jak robisz, mówisz wyraźnie, w której kolejności serializować/deserializować.

Kiedy więc XmlSerializer trafi do twojego elementu description, staje się on nieznanym elementem, ponieważ oczekuje elementu type. Resztę będą również traktowane jako nieznane elementy, ponieważ nie mapują one już na określone zamówienie. Na przykład, jeśli chodzi o twój element type, który ma indeks drugi w twoim XML, to spodziewa się, że będzie to element enabled, więc ten element również staje się nieznany.

Możesz sprawdzić to zachowanie, posługując się zdarzeniem UnknownNode klasy XmlSerializer. To zdarzenie zostanie uruchomione dla każdego napotkanego nieznanego węzła.

Jak postępować? Jeśli zamówienie nie ma znaczenia, nie używaj go. Są sytuacje, w których stosowanie zamawiania ma sens. Klasycznym przykładem, który widziałem wiele razy, są (starsze) aplikacje, które traktują dokumenty XML jako łańcuchy i czytają wszystkie elementy od góry do dołu.

Inną opcją byłaby implementacja interfejsu IXmlSerializer, który zapewnia lepszą kontrolę nad serializacją i deserializacją obiektu.

+0

Czy można pominąć atrybuty zamawianie tylko dla deserializacji? –

0

wiem, że to nie jest odpowiedź na to pytanie, ale myślę, że jeśli zmiana kierunku będzie rozwiązać problem ...

Czy utworzyć XSD do zdefiniowania schematu XML? Jeśli nie, polecam rozpocząć tam, a następnie użyć xsd2code, aby utworzyć klasę serializacji.

Powiązane problemy