XmlSerializer。跳过xml未知节点
我的 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>
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));
}
}
}
您可以看到该类不包含描述字段。
<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>
仅删除元素
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
默认情况下,XmlSerializer 会忽略未知节点(元素也是如此)。现在,当您像以前一样使用 Order 属性时,您将明确告知要序列化/反序列化的顺序。
因此,当 XmlSerializer 到达您的
description
元素时,它会成为未知元素,因为它需要type
元素。其余的也将受到未知元素的威胁,因为它们不再映射到您指定的订单。例如,当涉及到 XML 中索引为 2 的type
元素时,它期望它是enabled
元素,因此该元素也变得未知。您可以通过处理 UnknownNode 事件。对于遇到的每个未知节点,都会触发此事件。
如何进行?如果排序没有意义,请勿使用它。在某些情况下,使用排序确实有意义。我多次见过的一个经典示例是(遗留)应用程序,它们将 XML 文档视为字符串并从上到下读取所有元素。
另一种选择是实现 IXmlSerializer 接口,它可以让您更好地控制您的对象如何序列化和反序列化。
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 thetype
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 yourtype
element which has index two in your XML, it expects it be theenabled
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.
我知道这并不能回答你的问题,但我认为如果你改变方向它会解决你的问题...
你是否创建了 XSD 来定义 XML 架构?如果没有,我建议从这里开始,然后使用 xsd2code 创建序列化类。
I know this doesn't answer your question, but I think if you change directions it will solve your problem...
Did you create an XSD to define the XML Schema? If not, I recommend starting there and then using xsd2code to create the serialization class.
添加到 Martijn 的答案:
您还可以在数组中收集未知项目,以便稍后访问。
http://msdn.microsoft.com/en-us /library/system.xml.serialization.xmlanyelementattribute.aspx
To add to Martijn's answer:
You can also collect unknown items in an array which you can access later.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyelementattribute.aspx