JAXB 深入显出 - JAXB 教程 简单XML生成 Marshaller详解 - 属性

x33g5p2x  于2021-12-28 转载在 其他  
字(4.5k)|赞(0)|评价(0)|浏览(260)

摘要: JAXB 作为JDK的一部分,能便捷地将Java对象与XML进行相互转换,本教程从实际案例出发来讲解JAXB 2 的那些事儿。完整版目录

Marshaller 属性解析

为了能更多的举例,我采用单元测试的写法来验证代码。

第一个Java对象很简单: One.java

@XmlRootElement
public class One {

    private String name;
    // 省略 setters, getters
}

之前的章节中,已经介绍过,@XmlRootElement是必须的注解。

下面的代码有完整的注释:

@Test
    public void test() throws JAXBException {
        // 首先创建 JAXBContext
        JAXBContext jContext = JAXBContext.newInstance(One.class);
        // 初始化 Marshaller
        Marshaller marshaller = jContext.createMarshaller();
        // 创建简单的 Java bean
        One o = new One();
        o.setName("Test o");
        // 将结果输出到控制台
        marshaller.marshal(o, System.out);
    }

在控制台可以看到输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><one><name>Test one</name></one>

Marshaller.JAXB_FORMATTED_OUTPUT

结果是正确的,但是显示成一行不便于阅读,可以通过添加属性JAXB_FORMATTED_OUTPUT来修正:

在此之前,为了能重用 JAXBContext,可以只初始化一个实例,对代码稍微重构一下:

private static JAXBContext context;
    private static One one;

    @BeforeClass
    public static void init() throws JAXBException {
        // JAXBContext 是线程安全的 
        context = JAXBContext.newInstance(One.class);
        // 初始化全局的 Java bean
        one = new One();
        one.setName("Test one");
    }

这样可以更专注于核心逻辑,下面的代码使用JAXB_FORMATTED_OUTPUT来格式化输出:

@Test
    public void test1() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(one, System.out);
    }

得到的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<one>
    <id>11</id>
    <name>Test one</name>
</one>

看起来舒服很多。

Marshaller.JAXB_ENCODING

如果需要改输出XML的字符编码,可以添加属性JAXB_ENCODING

@Test
    public void test2() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-8859-1");
        marshaller.marshal(one, System.out);
    }

得到的结果:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<one>
    <name>Test one</name>
</one>

已经不再是默认的UTF-8

Marshaller.JAXB_SCHEMA_LOCATION

有时候,程序可能需要指定xsi:schemaLocation,则可以添加属性JAXB_SCHEMA_LOCATION

@Test
    public void test3() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd");
        marshaller.marshal(one, System.out);
    }

得到的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<one xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <name>Test one</name>
</one>

xsi:schemaLocation其实是Namespace为”http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd“里的schemaLocation属性,它定义了XML Namespace和对应的XSD(Xml Schema Definition)文档的位置的关系。在Spring的配置文件中,时常能见到这个属性。

Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION

如果没有Namespeace,但是需要使用Schema,就需要用到JAXB_NO_NAMESPACE_SCHEMA_LOCATION

@Test
    public void test4() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "ehcache.xsd");
        marshaller.marshal(one, System.out);
    }

得到的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<one xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
    <name>Test one</name>
</one>
Marshaller.JAXB_FRAGMENT

JAXB_FRAGMENT是一个多面手,在不同的输出场景下,表现出不同的效果。

@Test
    public void test5_1() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        marshaller.marshal(one, System.out);
    }

在这里指定JAXB_FRAGMENT=true,表明结果不再声明XML头信息,得到的结果:

<one>
    <name>Test one</name>
</one>

可以看到,第一行的XML声明不见了。

如果使用到了SAX方式(见下一小节),可以发现如下不同:

@Test
    public void test5_2() throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
        marshaller.marshal(one, new MyContentHandler());
    }

输出结果:

startDocument
endDocument

如果将注释的一行代码放开,再次运行程序将不能得到任何输出。JAXB_FRAGMENT的默认值为false,在其他场景下也有不同的表现。

下节预览

在下一节,将会讲述Marshaller支持的不同输出场景。

相关文章