之前很少用xml格式,但是有些老系统还是需要使用xml格式进行对接,所以干脆总结一下,方便以后使用。
关于xml:
即可扩展标记语言,xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。xml是当前处理结构化文档信息中相当给力的技术,xml有助于在服务器之间穿梭结构化数据,这使得开发人员更加得心应手的控制数据的存储和传输。
Xml用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。Xml是标准通用标记语言(SGML)的子集,非常适合Web传输。XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
也就是说xml有一个很大作用就是,跨平台跨系统之间的传输,这点跟json数据类似,不同的系统都能识别这种数据类型传输的信息。
一个xml文档必须要有第一行的声明和它的文档元素的描述信息就可以了:
也就是说第一行必须是声明。
声明的格式:
version:代表文档符合xml1.0规范
encoding:代表文档字符编码,默认编码为UTF-8
根元素结构如上所示,它是xml文档里面唯一的;它的开始是放在最前面,结束是放在最后面。
结构如上图所示,需要注意的是:
1、所有xml的元素都必须有结束标签
2、xml标签区分大小写,也就是对大小写敏感,如果大小写不一致会被认定不是同一个。
4、元素的命名规则:
·名称中可以包含字母、数字或者其他的字符;
·名称不能以数字或者标点符号开始;
·名称中不能包含空格。
5、空元素格式:
6、属性:
语法
<元素名 属性名=“属性值”/>
例:
注意:
属性值用双引号包裹;一个元素可以有多个属性,它的基本格式为:7、实体:
在xml中,一些字符拥有特殊的意义。如果把字符“<”放在xml元素中,会发生错误,这是因为解析器会把它当作新元素的开始,这样会产生xml错误:
为了避免这个错误,请用实体引用来代替“<”字符:
xml中5个预定义实体
8、注释
注:注释内容中不要出现”--”;不要把注释放在标签中间;注释不能嵌套。
9、总结:
(1)xml描述的是文档的内容与语义,而不是文档应当如何显示;
(2)格式正规(well formed)的xml文档,遵循如下规则的xml文档称为格式正规的xml文档:
·必须有xml声明语句;
·必须有且仅有一个根元素;
·标签大小写敏感;
·属性值用双引号;
·标签成对;
`空标签关闭;
`元素正确嵌套。
(3)有效的(valid)xml文档。首先xml文档是个格式正规的xml文档,然后又需要满足DTD的要求,这样的xml文档称为有效的xml文档;
以上就是关于xml格式介绍,其中还有很多细节,没有说,但是本次着重记录在java中的应用与转换,所以还有详细的内容可以自行查阅。
xml详解-CSDN博客
com.fasterxml.jackson.core
jackson-core
2.15.1
com.fasterxml.jackson.core
jackson-databind
2.15.1
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
2.15.1
跟jackson解析json格式一样,解析json使用ObjectMapper,解析xml格式主要使用XmlMapper。
主要靠的也是这两个方法:
writeValueAsString():将java对象转换为xml字符串。
readValue():将xml字符串转换为java对象。
其实使用的方式跟 json格式的转换时差不多,用的也是这两个方法,而且用之前最好先进行自定义配置一下,配置的方式跟json中ObjectMapper配置完全适用:
private static XmlMapper MAPPER = new XmlMapper();
static {
MAPPER = new XmlMapper();
//
// xmlMapper.setDefaultUseWrapper(false);
// //字段为null,自动忽略,不再序列化
xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// //XML标签名:使用骆驼命名的属性名,
// xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
// //设置转换模式
// xmlMapper.enable(MapperFeature.USE_STD_BEAN_NAMING);
// xmlMapper.registerModule(new JavaTimeModule());
//序列化所有属性,对象中属性为null的时候,会打印该属性为null
MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//序列化时,对象中属性为null的时候,会忽略该属性
// MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//序列化时,若POJO对象的属性值为"",序列化时不进行显示
// MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
//序列化时,忽略值为默认值的属性
// MAPPER.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
//美化输出,转换为格式化的json
MAPPER.enable(SerializationFeature.INDENT_OUTPUT);
//在遇到未知属性的时候不抛出异常。
MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//允许没有引号的字段名(非标准)出现。
MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
//允许单引号(非标准)
MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 允许整数以0开头
MAPPER.configure(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature(), true);
// 允许出现特殊字符和转义符
//mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);这个已经过时。
MAPPER.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
//关于Date类型参数序列化配置
//取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式
MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// MAPPER.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN));
//关于localDateTime类型参数序列化配置,不配会报错
// JavaTimeModule timeModule = new JavaTimeModule();
// //反序列化
// timeModule.addDeserializer(LocalDateTime.class, new
// LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// //系列化
// timeModule.addSerializer(LocalDateTime.class, new
// LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// MAPPER.registerModule(timeModule);
//上面的配置都不需要了,直接创建配置类即可
MAPPER.registerModule(new SatiJavaTimeModule());
SimpleModule simpleModule = new SimpleModule();
//将Long类型序列化为String类型
simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
//将BigDecimal类型序列化为String类型
simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
simpleModule.addSerializer(BigDecimal.class,new BigDecimalSerializer());
simpleModule.addSerializer(Long.class, new LongSerializer());
MAPPER.registerModule(simpleModule);
MAPPER.findAndRegisterModules();
}
然后就可以直接进行转换了:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private String age;
private LocalDateTime time;
private List strings;
}
ArrayList list = new ArrayList<>();
list.add("111");
list.add("111");
list.add("111");
Student student = new Student("姓名", "年龄", LocalDateTime.now(),list);
String xml = MAPPER.writeValueAsString(student);
System.out.println(xml);
Student student1 = MAPPER.readValue(xml, Student.class);
System.out.println(student1);
这是最简单的转换方式 。
一共六个注解,比较简约一点,其实主要使用的是这三个:
根元素:@JacksonXmlRootElement
根元素中包裹的其他元素:@JacksonXmlProperty
根元素中包裹的列表元素:@JacksonXmlElementWrapper
除去这三个还有@JsonIgnore比较常用,用于转xml格式时,忽略这个字段
@JacksonXmlText这个注解加上之后的效果就是会输出一个没有标签包裹的内容
@JacksonXmlCData主要是转换xml时,标签里面的内容指定。
示例:
@Data
@AllArgsConstructor
@NoArgsConstructor
@JacksonXmlRootElement(localName = "ROOT")
public class Student {
@JacksonXmlProperty(localName = "NAME",isAttribute = true)
private String name;
@JacksonXmlProperty(localName = "AGE")
private String age;
@JacksonXmlProperty(localName = "TIME")
private LocalDateTime time;
@JacksonXmlProperty(localName = "STRING")
@JacksonXmlElementWrapper(localName = "STRINGS")
private List strings;
}
ArrayList list = new ArrayList<>();
list.add("111");
list.add("111");
list.add("111");
Student student = new Student("姓名", "年龄", LocalDateTime.now(),list);
String xml = MAPPER.writeValueAsString(student);
System.out.println(xml);
@JacksonXmlProperty中的isAttribute = true,这个属性就会成为父标签中的内容。