xml java返回xml序列化化 怎么更新

51CTO旗下网站
浅析XML序列化的优缺点
XML序列化的优缺点是我们在使用XML序列化的过程中的经验总结,那么这些注意事项也是我们在开发的过程中对于XML序列化的选择的体现,希望对你学习XML序列化有所帮助。
作者:画圈圈的人来源:百度空间| 17:14
我们在.NET的学习过程中,是否发现了使用XML序列化的好处呢?XML序列化的好处是什么呢?还有就是有好处就会有一定的风险,那么我们在使用XML序列化的时候有需要注意什么呢?下面我们来详细看看具体的内容。
在XML序列化中我们会用到 XmlSerializer类,它在您将对象序列化为 XML 时为您提供完整而灵活的控制。如果您正在创建 XML Web services,则可以将控制序列化的属性应用于类和成员以确保 XML 输出符合特定的架构。
1、XML序列化之XmlSerializer使用所带来的好处:
◆指定应将字段或属性编码为特性还是元素。
◆指定要使用的 XML 命名空间。◆如果字段或属性名不合适,则指定元素或特性的名称。
◆XML序列化的另一个好处是:只要生成的XML流符合给定的架构,则对于所开发的应用程序就没有约束。假定有这样一个用于描述图书的架构,它具有标题、作者、出版商和 ISBN 编号元素。您可以开发一个以您希望的任何方式(例如,作为图书订单,或作为图书清单)处理 XML 数据的应用程序。在任一种情况下,唯一的要求是 XML 流应当符合指定的 XML 架构定义语言 (XSD) 架构。
2、XML 序列化注意事项:使用 XmlSerializer 类时,应考虑下列情况
◆序列化数据只包含数据本身以及类的结构。不包括类型标识和程序集信息。
◆只能序列化公共属性和字段。如果需要序列化非公共数据,请使用 BinaryFormatter 类而不是 XML 序列化。
◆类必须有一个将由 XmlSerializer 序列化的默认构造函数。
◆不能序列化方法。
XmlSerializer 可以以不同方式处理实现 IEnumerable 或 ICollection 的类(条件是这些类满足某些要求)。实现 IEnumerable 的类必须实现带单个参数的公共 Add 方法。Add 方法的参数必须与从 GetEnumerator 方法返回的 IEnumerator.Current 属性所返回的类型一致(多态)。除实现 IEnumerable 外还实现 ICollection 的类(如 CollectionBase)必须有一个取整数的公共 Item 索引属性(在 C# 中为索引器),并且它必须有一个整数类型的公共 Count 属性。传递给 Add 方法的参数必须与从 Item 属性返回的类型相同或与该类型的某个基的类型相同。对于实现 ICollection 的类,要序列化的值将从索引 Item 属性检索,而不是通过调用 GetEnumerator 来检索。另外请注意,除返回另一个集合类(实现 ICollection 的集合类)的公共字段之外,将不序列化公共字段和属性。有关示例,请参见 XML 序列化的示例。 XSD 数据类型映射
标题为“XML Schema Part 2: Datatypes”的万维网联合会 () 文档指定在 XML 架构定义语言 (XSD) 架构中允许使用的简单数据类型。对于这些数据类型中的许多类型(例如,int 和 decimal),在 .NET Framework 中都有对应的数据类型。但是,某些 XML 数据类型在 .NET Framework 中没有对应的数据类型(例如,NMTOKEN 数据类型)。在这样的情况下,如果使用 XML 架构定义工具 (Xsd.exe) 从架构生成类,就会将适当的特性应用于字符串类型的成员,并会将其 DataType 属性设置为 XML 数据类型名称。例如,如果架构包含一个数据类型为 XML 数据类型 NMTOKEN 的、名为“MyToken”的元素,则生成的类可能包含以下示例中的成员。
[Visual Basic]&XmlElement(DataType:="NMTOKEN")&Public MyToken As String[C#][XmlElement(DataType = "NMTOKEN")]public string MyT与此类似,如果创建一个必须符合特定 XML 架构 (XSD) 的类,应当应用适当的特性并将它的 DataType 属性设置为所需的 XML 数据类型名称。
关于XML序列化的使用优点以及XML序列化的使用注意事项就向你介绍到这里,希望对你了解和学习XML序列化有所帮助。
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
热点头条关注头条热点
24H热文一周话题本月最赞
讲师:30942人学习过
讲师:132080人学习过
讲师:12217人学习过
精选博文论坛热帖下载排行
本书介绍如何将最流行的J2EE应用服务器WebLogic Server和最好的Java集成开发工具JBuilder结合起来开发J2EE应用,主要内容包括:WebLogic Se...
订阅51CTO邮刊你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
我需要获得简单的xml,而不是&?xml version="1.0" encoding="utf-16"?&在开头,而xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"在XmlSerializer的第一个元素中。我该怎么做?
您可以使用XmlWriterSettings并将属性OmitXmlDeclaration设置为true,如。然后使用XmlSerializer.Serialize(xmlWriter,objectToSerialize)。
使用XmlSerializer.Serialize方法重载,您可以在其中指定自定义命名空间并将其传递给此。
var emptyNs = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
serializer.Serialize(xmlWriter, objectToSerialze, emptyNs);
传递null或空数组将无法解决问题
把这一切放在一起 - 这对我来说非常有用:
// To Clean XML
public string SerializeToString(T value)
var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent =
settings.OmitXmlDeclaration =
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
serializer.Serialize(writer, value, emptyNamepsaces);
return stream.ToString();
要回复问题请先或
最新活动: 2 天前
关注: 0 人&&&&&&&&&&&&&&&&&&
posts - 146,comments - 147,trackbacks - 0
随笔分类(157)
随笔档案(125)
收藏夹(13)
Java General
HBASE HADOOP INSTRUCTOR
Tech General
Tech resource from Oracle
Tech Master
concurrent package author
Distributed System, PAXOS author
MySQL/MongoDB/MariaDB
董的博客-大数据相关
积分与排名
阅读排行榜
评论排行榜
现在参与的项目是一个纯Application Server,整个Server都是自己搭建的,使用JMS消息实现客户端和服务器的交互,交互的数据格式采用XML。说来惭愧,开始为了赶进度,所有XML消息都是使用字符串拼接的,而XML的解析则是使用DOM方式查找的。我很早就看这些代码不爽了,可惜一直没有时间去重构,最近项目加了几个人,而且美国那边也开始渐渐的把这个项目开发的控制权交给我们了,所以我开始有一些按自己的方式开发的机会了。因而最近动手开始重构这些字符串拼接的代码。
对XML到Java Bean的解析框架,熟悉一点的只有Digester和XStream,Digester貌似只能从XML文件解析成Java Bean对象,所以只能选择XStream来做了,而且同组的其他项目也有在用XStream。一直听说XStream的使用比较简单,而且我对ThoughtWorks这家公司一直比较有好感,所以还以为引入XStream不会花太多时间,然而使用以后才发现XStream并没有想象的你那么简单。不过这个也有可能是因为我不想改变原来的XML数据格式,而之前的XML数据格式的设计自然不会考虑到如何便利的使用XStream。因而记录在使用过程中遇到的问题,供后来人参考,也为自己以后如果打算开其源码提供参考。废话就到这里了,接下来步入正题。
首先对于简单的引用,XStream使用起来确实比较简单,比如自定义标签的属性、使用属性和使用子标签的定义等:@XStreamAlias("request")public&class&XmlRequest1&{&&&&private&static&XStream&&&&&static&{&&&&&&&&xstream&=&new&XStream();&&&&&&&&xstream.autodetectAnnotations(true);&&&&}&&&&&&&@XStreamAsAttribute&&&&private&String&&&&&&&&@XStreamAsAttribute&&&&@XStreamAlias("calculate-method")&&&&private&String&calculateM&&&&&&&@XStreamAlias("request-time")& & private&Date&requestT&&&&&@XStreamAlias("input-files")&&&&private&List&InputFileInfo&&inputF&&&&&&&public&static&String&toXml(XmlRequest1&request)&{&&&&&&&&StringWriter&writer&=&new&StringWriter();&&&&&&&&writer.append(Constants.XML_HEADER);&&&&&&&&xstream.toXML(request,&writer);&&&&&&&&return&writer.toString();&&&&}&&&&public&static&XmlRequest1&toInstance(String&xmlContent)&{&&&&&&&&return&(XmlRequest1)xstream.fromXML(xmlContent);}&&&&@XStreamAlias("input-file")&&&&public&static&class&InputFileInfo&{&&&&&&&&private&String&&&&&&&&&private&String&fileN&&&&&&&&&&&&}&&&&public&static&void&main(String[]&args)&{&&&&&&&&XmlRequest1&request&=&buildXmlRequest();&&&&&&&&System.out.println(XmlRequest1.toXml(request));&&&&}&&&&private&static&XmlRequest1&buildXmlRequest()&{&&&&&&&&&&&&}}&对以上Request定义,我们可以得到如下结果:&?xml&version="1.0"&encoding="UTF-8"?&&request&from="levin@host"&calculate-method="advanced"&&&request-time&&17:11:54.664&UTC&/request-time&&&input-files&&&&&&input-file&&&&&&&&type&DATA&/type&&&&&&&&fileName&data..dat&/fileName&&&&&&/input-file&&&&&&input-file&&&&&&&&type&CALENDAR&/type&&&&&&&&fileName&calendar..dat&/fileName&&&&&&/input-file&&&/input-files&&/request&
可惜这个世界不会那么清净,这个格式有些时候貌似并不符合要求,比如request-time的格式、input-files的格式,我们实际需要的格式是这样的:&?xml&version="1.0"&encoding="UTF-8"?&&request&from="levin@host"&calculate-method="advanced"&&&request-time&:51:05&/request-time&&&input-file&type="DATA"&data..dat&/input-file&&&input-file&type="CALENDAR"&calendar..dat&/input-file&&/request&
对不同Date格式的支持可以是用Converter实现,在XStream中默认使用自己实现的DateConverter,它支持的格式是:yyyy-MM-dd HH:mm:ss.S 'UTC',然而我们现在需要的格式是yyyy-MM-dd’T’HH:mm:ss,如果使用XStream直接注册DateConverter,可以使用配置自己的DateConverter,但是由于DateConverter的构造函数的定义以及@XStreamConverter的构造函数参数的支持方式的限制,貌似DateConverter不能很好的支持注解方式的注册,因而我时间了一个自己的DateConverter以支持注解:public&class&LevinDateConverter&extends&DateConverter&{&&&&public&LevinDateConverter(String&dateFormat)&{&&&&&&&&super(dateFormat,&new&String[]&{&dateFormat&});&&&&}}
在requestTime字段中需要加入以下注解定义:@XStreamConverter(value=LevinDateConverter.class,&strings={"yyyyMMdd'T'HH:mm:ss"})@XStreamAlias("request-time")private&Date&requestT
对集合类,XStream提供了@XStreamImplicit注解,以将集合中的内容摊平到上一层XML元素中,其中itemFieldName的值为其使用的标签名,此时InputFileInfo类中不需要@XStreamAlias标签的定义:@XStreamImplicit(itemFieldName="input-file")private&List&InputFileInfo&&inputF
对InputFileInfo中的字段,type作为属性很容易,只要为它加上@XStreamAsAttribute注解即可,而将fileName作为input-file标签的一个内容字符串,则需要使用ToAttributedValueConverter,其中Converter的参数为需要作为字符串内容的字段名:@XStreamConverter(value=ToAttributedValueConverter.class,&strings={"fileName"})public&static&class&InputFileInfo&{&&&&@XStreamAsAttribute&&&&private&String&private&String&fileN}
XStream对枚举类型的支持貌似不怎么好,默认注册的EnumSingleValueConverter只是使用了Enum提供的name()和静态的valueOf()方法将enum转换成String或将String转换回enum。然而有些时候XML的字符串和类定义的enum值并不完全匹配,最常见的就是大小写的不匹配,此时需要写自己的Converter。在这种情况下,我一般会在enum中定义一个name属性,这样就可以自定义enum的字符串表示。比如有TimePeriod的enum:public&enum&TimePeriod&{&&&&MONTHLY("monthly"),&WEEKLY("weekly"),&DAILY("daily");&&&&&&&private&String&&&&&&&&public&String&getName()&{&&&&&&&&return&&&&&}&&&&&&&private&TimePeriod(String&name)&{&&&&&&&&this.name&=&&&&&}&&&&&&&public&static&TimePeriod&toEnum(String&timePeriod)&{&&&&&&&&try&{&&&&&&&&&&&&return&Enum.valueOf(TimePeriod.class,&timePeriod);&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&for(TimePeriod&period&:&TimePeriod.values())&{&&&&&&&&&&&&&&&&if(period.getName().equalsIgnoreCase(timePeriod))&{&&&&&&&&&&&&&&&&&&&&return&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&throw&new&IllegalArgumentException("Cannot&convert&&"&+&timePeriod&+&"&&to&TimePeriod&enum");&&&&&&&&}&&&&}}
我们可以编写以下Converter以实现对枚举类型的更宽的容错性:public&class&LevinEnumSingleNameConverter&extends&EnumSingleValueConverter&{&&&&private&static&final&String&CUSTOM_ENUM_NAME_METHOD&=&"getName";&&&&private&static&final&String&CUSTOM_ENUM_VALUE_OF_METHOD&=&"toEnum";&&&&&&&private&Class&?&extends&Enum&?&&&enumT&&&&&public&LevinEnumSingleNameConverter(Class&?&extends&Enum&?&&&type)&{&&&&&&&&super(type);&&&&&&&&this.enumType&=&&&&&}&&&&&@Override&&&&public&String&toString(Object&obj)&{&&&&&&&&Method&method&=&getCustomEnumNameMethod();&&&&&&&&if(method&==&null)&{&&&&&&&&&&&&return&super.toString(obj);&&&&&&&&}&else&{&&&&&&&&&&&&try&{&&&&&&&&&&&&&&&&return&(String)method.invoke(obj,&(Object[])null);&&&&&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&&&&&return&super.toString(obj);&&&&&&&&&&&&}&&&&&&&&}&&&&}&&&&&@Override&&&&public&Object&fromString(String&str)&{&&&&&&&&Method&method&=&getCustomEnumStaticValueOfMethod();&&&&&&&&if(method&==&null)&{&&&&&&&&&&&&return&enhancedFromString(str);&&&&&&&&}&&&&&&&&try&{&&&&&&&&&&&&return&method.invoke(null,&str);&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&return&enhancedFromString(str);&&&&&&&&}&&&&}&&&&&&&private&Method&getCustomEnumNameMethod()&{&&&&&&&&try&{&&&&&&&&&&&&return&enumType.getMethod(CUSTOM_ENUM_NAME_METHOD,&(Class&?&[])null);&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&return&null;&&&&&&&&}&&&&}&&&&&&&private&Method&getCustomEnumStaticValueOfMethod()&{&&&&&&&&try&{&&&&&&&&&&&&Method&method&=&enumType.getMethod(CUSTOM_ENUM_VALUE_OF_METHOD,&(Class&?&[])null);&&&&&&&&&&&&if(method.getModifiers()&==&Modifier.STATIC)&{&&&&&&&&&&&&&&&&return&&&&&&&&&&&&&}&&&&&&&&&&&&return&null;&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&return&null;&&&&&&&&}&&&&}&&&&&&&private&Object&enhancedFromString(String&str)&{&&&&&&&&try&{&&&&&&&&&&&&return&super.fromString(str);&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&for(Enum&?&&item&:&enumType.getEnumConstants())&{&&&&&&&&&&&&&&&&if(item.name().equalsIgnoreCase(str))&{&&&&&&&&&&&&&&&&&&&&return&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&throw&new&IllegalStateException("Cannot&converter&&"&+&str&+&"&&to&enum&&"&+&enumType&+&"&");&&&&&&&&}&&&&}}
如下方式使用即可:@XStreamAsAttribute@XStreamAlias("time-period")@XStreamConverter(value=LevinEnumSingleNameConverter.class)private&TimePeriod&timeP
对double类型,貌似默认的DoubleConverter实现依然不给力,它不支持自定义的格式,比如我们想在序列化的时候用一下格式:” ###,##0.0########”,此时又需要编写自己的Converter:public&class&FormatableDoubleConverter&extends&DoubleConverter&{&&&&private&String&&&&&private&DecimalFormat&&&&&&&&public&FormatableDoubleConverter(String&pattern)&{&&&&&&&&this.pattern&=&&&&&&&&&this.formatter&=&new&DecimalFormat(pattern);&&&&}&&&&&&&@Override&&&&public&String&toString(Object&obj)&{&&&&&&&&if(formatter&==&null)&{&&&&&&&&&&&&return&super.toString(obj);&&&&&&&&}&else&{&&&&&&&&&&&&return&formatter.format(obj);&&&&&&&&}&&&&}&&&&&&&@Override&&&&public&Object&fromString(String&str)&{&&&&&&&&try&{&&&&&&&&&&&&return&super.fromString(str);&&&&&&&&}&catch(Exception&ex)&{&&&&&&&&&&&&if(formatter&!=&null)&{&&&&&&&&&&&&&&&&try&{&&&&&&&&&&&&&&&&&&&&return&formatter.parse(str);&&&&&&&&&&&&&&&&}&catch(Exception&e)&{&&&&&&&&&&&&&&&&&&&&throw&new&IllegalArgumentException("Cannot&parse&&"&+&str&+&"&&to&double&value",&e);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&throw&new&IllegalArgumentException("Cannot&parse&&"&+&str&+&"&&to&double&value",&ex);&&&&&&&&}&&&&}&&&&&&&public&String&getPattern()&{&&&&&&&&return&&&&&}}
使用方式和之前的Converter类似:@XStreamAsAttribute@XStreamConverter(value=FormatableDoubleConverter.class,&strings={"###,##0.0########"})private&double&
最后,还有两个XStream没法实现的,或者说我没有找到一个更好的实现方式的场景。第一种场景是XStream不能很好的处理对象组合问题:
在面向对象编程中,一般尽量的倾向于抽取相同的数据成一个类,而通过组合的方式构建整个数据结构。比如Student类中有name、address,Address是一个类,它包含city、code、street等信息,此时如果要对Student对象做如下格式序列化:&student&name=”Levin”&&&city&shanghai&/city&&&street&zhangjiang&/street&&&code&201203&/code&&/student&
貌似我没有找到可以实现的方式,XStream能做是在中间加一层address标签。对这种场景的解决方案,一种是将Address中的属性平摊到Student类中,另一种是让Student继承自Address类。不过貌似这两种都不是比较理想的办法。
第二种场景是XStream不能很好的处理多态问题:
比如我们有一个Trade类,它可能表示不同的产品:public&class&Trade&{&&&&private&String&tradeId;& & private&Product&}abstract&class&Product&{&&&&private&String&&&&&public&Product(String&name)&{&&&&&&&&this.name&=&}}class&FX&extends&Product&{&&&&private&double&&&&&public&FX()&{&&&&&&&&super("fx");&&&&}&&&&}class&Future&extends&Product&{&&&&private&double&&&&&public&Future()&{&&&&&&&&super("future");&&&&}&&&&}
通过一些简单的设置,我们能得到如下XML格式:&trades&&&trade&trade-id="001"&&&&&&product&class="levin.xstream.blog.FX"&name="fx"&ratio="0.59"/&&&/trade&&&trade&trade-id="002"&&&&&&product&class="levin.xstream.blog.Future"&name="future"&maturity="2.123"/&&&/trade&&/trades&
作为数据文件,对Java类的定义显然是不合理的,因而简单一些,我们可以编写自己的Converter将class属性从product中去除:xstream.registerConverter(new&ProductConverter(&&&&&&&&xstream.getMapper(),&xstream.getReflectionProvider()));&&&&&public&ProductConverter(Mapper&mapper,&ReflectionProvider&reflectionProvider)&{&&&&&&&&super(mapper,&reflectionProvider);&&&&}&&&&&&&@Override&&&&public&boolean&canConvert(@SuppressWarnings("rawtypes")&Class&type)&{&&&&&&&&return&Product.class.isAssignableFrom(type);&&&&}&&&&&@Override&&&&protected&Object&instantiateNewInstance(HierarchicalStreamReader&reader,&UnmarshallingContext&context)&{&&&&&&&&Object&currentObject&=&context.currentObject();&&&&&&&&if(currentObject&!=&null)&{&&&&&&&&&&&&return&currentO&&&&&&&&}&&&&&&&&&&&&&&&String&name&=&reader.getAttribute("name");&&&&&&&&if("fx".equals(name))&{&&&&&&&&&&&&return&reflectionProvider.newInstance(FX.class);&&&&&&&&}&else&if("future".equals(name))&{&&&&&&&&&&&&return&reflectionProvider.newInstance(Future.class);&&&&&&&&}&&&&&&&&throw&new&IllegalStateException("Cannot&convert&&"&+&name&+&"&&product");&&&&}}
在所有Production上定义@XStreamAlias(“product”)注解。这时的XML输出结果为:&trades&&&trade&trade-id="001"&&&&&&product&name="fx"&ratio="0.59"/&&&/trade&&&trade&trade-id="002"&&&&&&product&name="future"&maturity="2.123"/&&&/trade&&/trades&
然而如果有人希望XML的输出结果如下呢?&trades&&&trade&trade-id="001"&&&&&&fx&ratio="0.59"/&&&/trade&&&trade&trade-id="002"&&&&&&future&maturity="2.123"/&&&/trade&&/trades&
大概找了一下,可能可以定义自己的Mapper来解决,不过XStream的源码貌似比较复杂,没有时间深究这个问题,留着以后慢慢解决吧。补充:
对Map类型数据,XStream默认使用以下格式显示:&map&class="linked-hash-map"&&&&&&entry&&&&&&&&string&key1&/string&&&&&&&&string&value1&/string&&&&&&/entry&&&&&&entry&&&&&&&&string&key2&/string&&&&&&&&string&value2&/string&&&&&&/entry&&&/map&&
但是对一些简单的Map,我们希望如下显示:&&map&&&&&&entry&key="key1"&value="value1"/&&&&&&entry&key="key2"&value="value2"/&&&/map&
对这种需求需要通过编写Converter解决,继承自MapConverter,覆盖以下函数,这里的Map默认key和value都是String类型,如果他们不是String类型,需要另外添加逻辑:@SuppressWarnings("rawtypes")@Overridepublic&void&marshal(Object&source,&HierarchicalStreamWriter&writer,&&&&&&&&MarshallingContext&context)&{&&&&Map&map&=&(Map)&&&&&for&(Iterator&iterator&=&map.entrySet().iterator();&iterator.hasNext();)&{&&&&&&&&Entry&entry&=&(Entry)&iterator.next();&&&&&&&&ExtendedHierarchicalStreamWriterHelper.startNode(writer,&mapper()&&&&&&&&&&&&&&&&.serializedClass(Map.Entry.class),&entry.getClass());&&&&&&&&&writer.addAttribute("key",&entry.getKey().toString());&&&&&&&&writer.addAttribute("value",&entry.getValue().toString());&&&&&&&&writer.endNode();&&&&}}&@Override@SuppressWarnings({&"unchecked",&"rawtypes"&})protected&void&putCurrentEntryIntoMap(HierarchicalStreamReader&reader,&&&&&&&&UnmarshallingContext&context,&Map&map,&Map&target)&{&&&&Object&key&=&reader.getAttribute("key");&&&&Object&value&=&reader.getAttribute("value");&&&&&target.put(key,&value);}
但是只是使用Converter,得到的结果多了一个class属性:&&map&class="linked-hash-map"&&&&&&entry&key="key1"&value="value1"/&&&&&&entry&key="key2"&value="value2"/&&&/map&
在XStream中,如果定义的字段是一个父类或接口,在序列化是会默认加入class属性以确定反序列化时用的类,为了去掉这个class属性,可以定义默认的实现类来解决(虽然感觉这种解决方案不太好,但是目前还没有找到更好的解决方案)。
xstream.addDefaultImplementation(LinkedHashMap.class,&Map.class);&
阅读(20026)
&re: 使用XStream序列化、反序列化XML数据时遇到的各种问题
厉害。最后一部份写的,真是精彩。&&&&&&
&re: 使用XStream序列化、反序列化XML数据时遇到的各种问题
楼主你好,不知道继承的那个问题你有没有解决掉?我现在也遇到这个问题,如果你解决掉麻烦讲解一下,谢谢&&&&&&
&re: 使用XStream序列化、反序列化XML数据时遇到的各种问题
继承上,子类对象 在toxml时,
XStream只将子类的属性转xml了, 父类的属性没转换xml为何呢?&&&&&&自定义文件存储和 XML 序列化
不是 IT 专业人员?
TechNet 库
建议使用 Visual Studio 2017
自定义文件存储和 XML 序列化
Visual Studio 2015
若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 。当用户保存实例,或 模型, ,域特定语言 (DSL) 中的 Visual Studio, ,创建或更新的 XML 文件。 可以重新加载文件以重新创建存储区中的模型。可以通过调整下的设置来自定义序列化方案 Xml 序列化行为 DSL 资源管理器中。 没有下的节点 Xml 序列化行为 为每个域类、 属性和关系。 关系都位于其源类下。 也有对应于形状、 连接器和关系图类节点。你还可以编写更多高级自定义项的程序代码。 说明
如果你想要将模型保存为特定的格式,但不是需要从该窗体重新加载它,请考虑使用文本模板的模型,而不是自定义序列化方案从生成输出。 有关详细信息,请参阅 。每个模型通常保存在两个文件︰模型文件有一个名称,如 Model1.mydsl。 它将存储的模型元素和关系和它们的属性。 文件扩展名,例如 .mydsl 由 FileExtension 属性 编辑器 DSL 定义中的节点。关系图文件有一个名称,如 Model1.mydsl.diagram。 它将存储形状、 连接器,和它们的位置、 颜色、 线厚度和关系图的外观的其他详细信息。 如果用户删除 .diagram 文件,在模型中的基本信息不会丢失。 仅关系图的布局将丢失。 当打开模型文件时,一组默认的形状并将创建连接器。打开 DSL 定义。 在 DSL 资源管理器,单击编辑器节点。在属性窗口中,编辑 FileExtension 属性。 不包括初始"。"的文件扩展名。在解决方案资源管理器,更改中的两个项模板文件的名称 DslPackage\ProjectItemTemplates。 这些文件具有遵循以下格式的名称︰myDsl.diagrammyDsl.myDsl若要创建一个用于本主题的示例,使用以下 DSL 定义。此 DSL 用于创建在屏幕具有以下外观的模型。此模型进行保存,然后重新在 XML 文本编辑器中打开它︰
&?xml version="1.0" encoding="utf-8"?&
&familyTreeModel xmlns:dm0="http://schemas.microsoft.com/VisualStudio/2008/DslTools/Core" dslVersion="1.0.0.0" Id="f817b728-e920-458e-bb99-98edc469d78f" xmlns="http://schemas.microsoft.com/dsltools/FamilyTree"&
&person name="Henry VIII" birthYear="1491" deathYear="1547" age="519"&
&children&
&personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" /&
&personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Mary" /&
&/children&
&person name="Elizabeth I" birthYear="1533" deathYear="1603" age="477" /&
&person name="Mary" birthYear="1515" deathYear="1558" age="495" /&
&/familyTreeModel&
请注意有关序列化模型的以下几点︰每个 XML 节点具有与域类名,相同的名称,只是初始字母为小写。 例如, familyTreeModel 和 person。域属性,如名称和 BirthYear 扩展会序列化为 XML 节点中的属性。 同样,将属性名称的初始字符转换为小写。每个关系序列化为 XML 节点嵌套在关系的源端。 该节点具有相同名称,为源角色属性,但大小写的初始字符。例如,在 DSL 定义中,名为的角色 人员 源自在 FamilyTree 类。
在 XML 中,它通过名为的节点中表示 people 嵌套在 familyTreeModel 节点。每个嵌入的关系的目标端序列化为嵌套在关系的节点。 例如, people 节点包含若干 person 节点。每个引用关系的目标端序列化为 标记, ,这将编码目标元素的引用。例如,在 person 节点,可以有 children 关系。 此节点包含名字对象,例如︰
&personMoniker name="/f817b728-e920-458e-bb99-98edc469d78f/Elizabeth I" /&
名字对象用于表示的模型和关系图文件不同部分之间的交叉引用。 它们也用在 .diagram 文件来指代模型文件中的节点。 有两种形式的名字对象︰Id 名字对象 quote 目标元素的 GUID。 例如:
&personShapeMoniker Id="fda1-4d72-e75157" /&
限定密钥名字对象 通过称为标记密钥指定的域属性的值标识的目标元素。 目标元素的名字对象是由其父元素的嵌入关系树中的名字对象的前缀。下面的示例将从有在其中 DSL 是一个名为唱片集,具有类命名首歌曲关系嵌入到域的域类︰
&albumMoniker title="/My Favorites/Jazz after Teatime" /&
&songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" /&
如果目标类具有为其域属性,则将使用限定密钥名字对象选项 名字对象键 设置为 true 中 Xml 序列化行为。 在示例中,此选项设置为"唱片集"和"歌曲"的域类中名为"Title"域属性。限定密钥名字对象更易于读取比 ID 名字对象。 如果你想要的人员无法读取模型文件的 XML,请考虑使用限定密钥名字对象。 但是,它是用户可以设置多个元素可以有相同的名字对象键。 重复的键可能会导致文件无法正确地重新加载。 因此,如果你定义使用限定密钥名字对象引用的域类,则应考虑阻止用户保存具有重复的名字对象的文件的方式。请确保 名字对象键 是 false 每个域中为属性类和基类。DSL 资源管理器,展开 Xml 序列化 Behavior\Class 数据\& 域类&\Element 数据。验证 名字对象键 是 false 对于每个域属性。如果域类具有的基的类,请重复该类中的过程。设置 序列化 Id = true 域类。此属性可以下找到 Xml 序列化行为。设置 名字对象键 现有域类域属性。 属性的类型必须是 string。DSL 资源管理器,展开 Xml 序列化 Behavior\Class 数据\& 域类&\Element 数据, ,然后选择域属性。在属性窗口中,设置 名字对象键 到 true。- 或-创建新的域类使用 名为域类 工具。此工具创建具有一个名为名称的域属性的新类。
是元素名称 和 名字对象键 此域属性的属性初始化为 true。- 或-与具有名字对象键属性的另一个类,从域类中创建一个继承关系。如果你使用限定密钥名字对象,则可能在用户的模型中的两个元素,无法键属性中有相同的值。 例如,如果 DSL 具有类具有一个属性名称的人员,用户可以设置的两个元素的名称相同。 虽然该模型可能是保存到文件,它将不重新加载正确。有几种方法,可帮助避免这种情况︰设置 是元素名称 = true 密钥域属性。 选择 DSL 定义关系图上的域属性,然后在属性窗口中设置值。当用户创建的类的新实例时,此值会导致自动分配一个不同的值的 domain 属性。 默认行为的类名称的末尾添加一个数字。 这不会阻止用户的名称更改为有重复,但它有助于在情况下用户在保存模型之前未设置的值。启用 DSL 的验证。 DSL 资源管理器,在选择 Editor\Validation,并设置 ...使用 属性设置为 true。没有多义性检查自动生成的验证方法。 该方法是在 Load 验证类别。 这样可以确保,用户会收到警告,它可能无法重新打开该文件。有关详细信息,请参阅 。限定的密钥标记结束与名字对象的键,并带有嵌入的树中其父代的标记前缀。 例如,如果唱片集的名字对象为︰
&albumMoniker title="/My Favorites/Jazz after Teatime" /&
那么该唱片集中歌曲之一可能为︰
&songMoniker title="/My Favorites/Jazz after Teatime/Hot tea" /&
但是,如果专辑改为引用的 ID,然后名字对象将,如下所示︰
&albumMoniker Id="bf9-a-d97a4745237c" /&
&songMoniker title="/bf9-a-d97a4745237c/Hot tea" /&
请注意,GUID 是唯一的因为它从不前缀由其父级的名字对象。如果你知道特定域属性,将始终具有一个模型中的唯一值,则可以设置 是名字对象限定符 到 true 该属性。 这将导致它要用作限定符,而无需使用的父标记。 例如,如果同时设置 是名字对象限定符 和 名字对象键 唱片集类的标题域属性,该模型的名称或标识符中不使用名字对象为唱片集及其嵌入的子级︰
&albumMoniker name="Jazz after Teatime" /&
&songMoniker title="/Jazz after Teatime/Hot tea" /&
若要进行以下自定义,展开 Xml 序列化行为 DSL 资源管理器中的节点。 下的域类中,展开若要查看的属性和关系,以指明其出处的此类在列表的元素数据节点。 选择一个关系,并调整其属性窗口中的选项。设置 省略元素 为 true,若要省略源角色节点,只需目标元素的列表。 如果源和目标类之间没有多个关系,不应设置此选项。
&familyTreeModel ...&
&!-- The following node is omitted by using Omit Element: --&
&!-- &people& --&
&person name="Henry VIII" .../&
&person name="Elizabeth I" .../&
&!-- &/people& --&
&/familyTreeModel&
设置 使用完整的窗体 将目标节点嵌入节点表示关系实例。 域属性添加到域关系时,将自动设置此选项。
&familyTreeModel ...&
&!-- The following node is inserted by using Use Full Form: --&
&familyTreeModelHasPeople myRelationshipProperty="x1"&
&person name="Henry VIII" .../&
&/familyTreeModelHasPeople&
&familyTreeModelHasPeople myRelationshipProperty="x2"&
&person name="Elizabeth I" .../&
&/familyTreeModelHasPeople&
&/familyTreeModel&
设置 表示 = 元素 为具有域属性保存与某一元素,而不是作为属性值。
&person name="Elizabeth I" birthYear="1533"&
&deathYear&1603&/deathYear&
若要更改在其中属性和关系进行序列化的顺序,右键单击受元素数据的项,并使用 移 或 下移 菜单命令。你可以将部分或全部的序列化算法。我们建议你先研究中的代码 Dsl\Generated Code\Serializer.cs 和 SerializationHelper.cs。设置 是自定义 中的节点下该类 Xml 序列化行为。转换所有模板生成该解决方案,然后调查生成编译错误。 接近每个错误的注释说明了你必须提供哪些代码。重写中 Dsl\GeneratedCode\SerializationHelper.cs 方法DSL 资源管理器,在 Xml 序列化行为节点包含每个域类、 关系、 形状、 连接器和关系图类的子节点。 在每个这些节点是的属性和关系源于该元素的列表。 在其自己右和下它们的源类表示关系。下表总结了你可以在此部分的 DSL 定义中设置的选项。 在每个情况下,在 DSL 资源管理器,选择某个元素和设置属性窗口中的选项。在下的 DSL 资源管理器中找到这些元素 Xml 序列化 Behavior\Class 数据。属性描述具有自定义元素的架构如果为 True,指示域类具有自定义元素的架构为自定义将其设置为 True 如果你想要编写此域类自己序列化和反序列化代码。 生成解决方案并调查要发现的详细的说明的错误。域类此类数据节点应用到的域类。 只读。元素名称此类的元素的 Xml 节点名称。 默认值为域类名称的小写版本。名字对象属性名称标记元素以包含引用的属性的名称。 如果保留为空,则使用的键属性或 id 的名称。 在此示例中,它是"name":
&personMoniker name="/Mike Nash"/&标记元素名称用于引用此类的元素的名字对象的 xml 元素的名称。 默认值为"标记"后缀的类名称的小写版本。 例如 personMoniker。标记类型名称为此类的元素的名字对象生成的 xsd 类型的名称。 XSD 处于 Dsl\Generated 代码\*Schema.xsd序列化 Id如果为 True,在文件中包含该元素 GUID。 这必须是 true,如果没有任何属性标记为可供 名字对象键 和 DSL 定义与此类的引用关系。类型名称在指定的域类从 xsd 中生成的 xml 类型的名称。备注与此元素关联的非正式说明在类节点下找到 Xml 属性节点。属性描述域属性Xml 序列化配置数据应用的属性。 只读。是标记密钥如果为 True,则属性用作创建引用此域类的实例的名字对象的键。是标记限定符如果为 True,该属性用于创建限定符名字对象中。 如果为 false,和 SerializeId 未得到满足此域类,名字对象被限定中嵌入的树的父元素的标记。表示形式如果属性,该属性序列化为 xml 特性;如果元素,它是序列化为的元素;如果忽略,则不序列化。Xml 名称用于 xml 特性或元素表示的属性的名称。 默认情况下,这是域的属性名称的小写版本。备注与此元素关联的非正式说明角色数据节点的源类节点下找到。属性描述具有自定义标记设置为 true,如果你想要提供自己的代码生成和解决遍历此关系的名字对象。 有关详细说明,构建解决方案,,然后双击的错误消息。域关系指定要应用这些选项的关系。 只读。省略元素如果为 true,架构中省略对应的源角色的 XML 节点。 如果源和目标类之间没有多个关系,此角色节点会区分属于两个关系的链接。 因此,我们建议,未设置此选项在此情况下。角色元素名称指定派生自的源角色的 XML 元素的名称。 默认值为角色属性名称。使用完整的窗体如果为 true,每个目标元素或标记括在 XML 节点表示关系中。 这应设置为 true,如果关系具有其自己的域属性。
此页面有帮助吗?
更多反馈?
1500 个剩余字符
我们非常感谢您的反馈。
页面加载速度够快吗?
您喜欢网页的设计吗?
请告诉我们更多意见}

我要回帖

更多关于 c#xml序列化 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信