Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c# - XmlSerializer. Skip xml unknown node

I have a problem with deserialization of my xml files. Let's pretend that we have a xml file and a class that we are using for deserialization to.

For example:

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>

Class

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 this.@__defaultField;
            }
            set
            {
                this.@__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));
        }
    }
}

You can see that the class doesn't contain description field.

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

You can see that all elements after description were not be deserialized.

When program gets xml content and this xml contains an element that isn't in the class all elements after this element won't be desirialized.

How can I skip unknown element during deserialization and get something like this:

<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>

remove only element

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By default the XmlSerializer ignores unknown nodes (so elements as well). Now when you use the Order property like you do, you are telling explicitly in which Order to serialize/deserialize.

So when the XmlSerializer comes to your description element this becomes a unknown element because it expects the type element. The rest will also be threated as unknown elements because they do not map anymore to your specified order. For example when it comes to your type element which has index two in your XML, it expects it be the enabled element so this element becomes unknown as well.

You can check this behaviour by handling the UnknownNode event of the XmlSerializer class. This event will be fired for every unknown node it encounters.

How to proceed? If the ordering has no meaning don't use it. There are situations where it does make sense to use ordering. A classical example I've seen multiple times are (legacy) apps which treat XML documents as strings and read all the elements from top to bottom.

Another option would be implementing the IXmlSerializer interface, which gives you better control on how your object is serialized and deserialized.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...