XmlSerializer. Пропустить неизвестный узел xml - PullRequest
5 голосов
/ 26 июля 2011

У меня проблема с десериализацией моих XML-файлов.Давайте представим, что у нас есть XML-файл и класс, который мы используем для десериализации.

Например:

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>

Класс

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));
        }
    }
}

Вы видите, что класс не содержит поля описания.

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

Вы можете видеть, что все элементы после описания не были десериализованы.

Когда программа получает контент XML, и этот XML содержит элемент, который не входит в класс всех элементов после этогоэлемент не будет десериализован.

Как пропустить неизвестный элемент во время десериализации и получить что-то вроде этого:

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

удалить только элемент

Ответы [ 3 ]

9 голосов
/ 30 ноября 2011

По умолчанию XmlSerializer игнорирует неизвестные узлы (так же как и элементы).Теперь, когда вы используете свойство Order, как и вы, вы явно указываете, в каком порядке сериализовать / десериализовать Order.

Поэтому, когда XmlSerializer подходит к вашему элементу description, он становится неизвестным элементом, поскольку он ожидает type элемент.Остальные также будут представлены как неизвестные элементы, поскольку они больше не отображаются в указанном вами порядке.Например, когда дело доходит до вашего элемента type с индексом два в вашем XML, он ожидает, что это будет элемент enabled, поэтому этот элемент также становится неизвестным.

Вы можете проверить это поведение, обработав UnknownNode событие класса XmlSerializer.Это событие будет вызываться для каждого неизвестного узла, с которым он сталкивается.

Как продолжить?Если порядок не имеет смысла, не используйте его.Есть ситуации, когда имеет смысл использовать порядок.Классическим примером, который я видел несколько раз, являются (унаследованные) приложения, которые обрабатывают документы XML как строки и читают все элементы сверху вниз.

Другой вариант - реализация интерфейса IXmlSerializer , что дает вам лучший контроль над сериализацией и десериализацией вашего объекта.

0 голосов
/ 15 июля 2014

Чтобы добавить к ответу Мартин:

Вы также можете собирать неизвестные элементы в массив, к которому вы можете обратиться позже.

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyelementattribute.aspx

Public Class XClass
    ' Apply the XmlAnyElementAttribute to a field returning an array 
    ' of XmlElement objects.
    <XmlAnyElement()> Public AllElements() As XmlElement
End Class 'XClass
0 голосов
/ 30 ноября 2011

Я знаю, что это не отвечает на ваш вопрос, но я думаю, что если вы измените направление, это решит вашу проблему ...

Вы создали XSD для определения схемы XML? Если нет, я рекомендую начать там и затем использовать xsd2code для создания класса сериализации.

...