java中XML格式转换

发布时间:2023年12月27日

????????之前很少用xml格式,但是有些老系统还是需要使用xml格式进行对接,所以干脆总结一下,方便以后使用。

关于xml:

可扩展标记语言,xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。xml是当前处理结构化文档信息中相当给力的技术,xml有助于在服务器之间穿梭结构化数据,这使得开发人员更加得心应手的控制数据的存储和传输。

Xml用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。Xml是标准通用标记语言(SGML)的子集,非常适合Web传输。XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

也就是说xml有一个很大作用就是,跨平台跨系统之间的传输,这点跟json数据类似,不同的系统都能识别这种数据类型传输的信息。

一、xml格式:?

一个xml文档必须要有第一行的声明和它的文档元素的描述信息就可以了:

1)xml声明:

也就是说第一行必须是声明。
声明的格式:

version:代表文档符合xml1.0规范
encoding:代表文档字符编码,默认编码为UTF-8

2)根元素

声明下方的标签就是根元素。

?根元素结构如上所示,它是xml文档里面唯一的;它的开始是放在最前面,结束是放在最后面。

3)元素

根元素中包裹的就是元素:

结构如上图所示,需要注意的是:
1、所有xml的元素都必须有结束标签
2、xml标签区分大小写,也就是对大小写敏感,如果大小写不一致会被认定不是同一个。
?

?3、xml必须正确地嵌套,要按照顺序嵌套:

4、元素的命名规则:
? ? ? ? ·名称中可以包含字母、数字或者其他的字符;
? ? ? ? ·名称不能以数字或者标点符号开始;
? ? ? ? ·名称中不能包含空格。
5、空元素格式:

6、属性:

  • 语法

    <元素名?属性名=“属性值”/>

    例:<Student?ID=“S100”>

    ???????<Name>Tom</Name>

    ???????</Student>

  • 注意:

    属性值用双引号包裹;一个元素可以有多个属性,它的基本格式为:
    ????????<元素名?属性名=“属性值”?属性名=“属性值”>;

    属性值中不能够直接包含<.”,&。

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

二、使用Jackson解析xml

1)引入依赖:
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.15.1</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.1</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.15.1</version>
        </dependency>
2)XmlMapper:

跟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<String> strings;
}
        ArrayList<String> 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);

这是最简单的转换方式 。

3)jackson解析xml相关注解:
  • @JacksonXmlRootElement
    指定生成xml根标签的名字。用于类名,是xml最外层的根节点。注解中有localName属性,该属性如果不设置,那么生成的XML最外面就是Clazz。
  • @JacksonXmlProperty
    指定包装标签名,或者指定标签内部属性名。该注解通常可以不需要,若不用,生成xml标签名称就是实体类属性名称。但是如果你想要你的xml节点名字,首字母大写。比如例子中的Content,那么必须加这个注解,并且注解的localName填上你想要的节点名字。最重要的是实体类原来的属性content必须首字母小写!否则会被识别成两个不同的属性。注解的isAttribute,确认是否为节点的属性,如下图中的“gradeId”。
  • @JacksonXmlElementWrapper
    用于指定List等集合类,外围标签名;用在非集合类上无效。一般用于list,list外层的标签。若不用的话,useWrapping =false。
  • @JacksonXmlText
    指定当前这个值,没有xml标签包裹。用实体类属性上,说明该属性是否为简单内容,如果是,那么生成xml时,不会生成对应标签名称。
  • @JsonIgnore
    忽略该实体类的属性,该注解是用于实体类转json的,但用于转xml一样有效,具体原因个人推测是XmlMapper是ObjectMapper的子类。
  • @JacksonXmlCData
    是为了生成<![CDATA[text]]>。

一共六个注解,比较简约一点,其实主要使用的是这三个:
? ? ? ? 根元素:@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<String> strings;
}
        ArrayList<String> 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,这个属性就会成为父标签中的内容。

文章来源:https://blog.csdn.net/kkkkatoq/article/details/135237585
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。