JAXB解析xml

一。概述

JAXB(Java Architecture for XML Binding)是由 J2EE 体系中标准的 XML schema 和 Java 数据绑定框架,开发者可以使用 JAXB 方便地在 Java 应用程序中进行XML 数据和 Java 对象的转换。JAXB 提供了将 XML 文档解析为 Java 内容树的方法,以及将 Java 内容树重新写回 XML 文档的方法。同时 JAXB 还提供了基于 XML schema 生成 Java 类以及从 Java 类生成 XML schema 的支持。

    JAXBContext 类提供到 JAXB API 的客户端入口点。它提供了管理实现 JAXB 绑定框架操作所需的 XML/Java 绑定信息的抽象,这些操作包括:解组、编组和验证。

  在JDK1.6时,JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。

 JDK中JAXB相关的重要Class和Interface:

  1、JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。

  2、Marshaller接口,将Java对象序列化为XML数据。

  3、Unmarshaller接口,将XML数据反序列化为Java对象。

 

二.JDK中JAXB相关的重要Annotation:

 

  1、@XmlType,将Java类或枚举类型映射到XML模式类型

@XmlType 注解用于标注类或枚举类型,用它标注的类在映射后的 schema 中中会以一个 XML 复杂数据类型的形式出现

参数:propOrder        指定映射XML时的节点顺序,来指定输出顺序,来定制映射后的复杂数据类型的内容顺序

         factoryClass     指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身

         factoryMethod  指定工厂类的工厂方法

         name               定义XML Schema中type的名称,定制映射的 XML 数据类型的名称

         namespace      指定Schema中的命名空间

例:

  2、@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标注)字段到XML。其他值还有XmlAccessType.PROPERTY(映射这个类中的属性(get/set方法)到XML)和XmlAccessType.NONE, XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)

       例如:@XmlAccessorType(XmlAccessType.FIELD)
           @XmlAccessorType(value = XmlAccessType.PROPERTY) 

  3、@XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。

  4、@XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。

    自定义某一字段或属性映射到XML的适配器。如,类中包含一个接口,我们可以定义一个适配器(继承自javax.xml.bind.annotation.adapters.XmlAdapter类),指定这个接口如何映射到XML。

  5、@XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。

  为数组元素或集合元素定义一个父节点。如,类中有一元素为List items,若不加此注解,该元素将被映射为

    <items>...</items>

    <items>...</items>

这种形式,此注解可将这个元素进行包装,如:

    @XmlElementWrapper(name="items") 
    @XmlElement(name="item") 
    public List items;

将会生成这样的XML样式:

    <items>

        <item>...</item>

        <item>...</item>

    </items>

 

 

 

  6、@XmlRootElement,将Java类或枚举类型映射到XML元素。

      注解用于标注类或枚举类型,用它标注的类在映射后的 schema 中会以一个全局元素的形式出现

参数:name   定制映射的 schema 全局元素的名称,一般来说以 @XmlRootElement 标注的类在相应的 XML 文档中会以最外层或根节点形式出现。

      namespace    定义这个根节点命名空间, XML元素的名称空间名
例:

  7、@XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素。

          @XmlElement 注解用于标注 Javabean 的属性,用它标注的属性在映射后的 schema 中以元素的形式出现,所有 Javabean 属性映射的元素组合成为
  @XmlType 映射的复杂数据类型.
2)指定一个字段或get/set方法映射到XML的节点。如,当一个类的XmlAccessorType 被标注为PROPERTY时,在某一个没有get/set方法的字段上标注此注解,
即可将该字段映射到XML。

参数:defaultValue  指定节点默认值

           name             指定节点名称,定制映射后的 XML 元素的名称

          namespace    指定节点命名空间

          required         指定该元素是否必须出现.是否必须(默认为false)required() 为 true,则将Javabean 属性映射到一个 minOccurs="1" 的 XML 模式元素声明                              。maxOccurs为 "1" 表示单个赋值的属性,maxOccurs 为 "unbounded" 则表示多个赋值的属性。

         nillable           该字段是否包含 nillable="true" 属性(默认为false)

         type               定义该字段或属性的关联类型
例:


 

  8、@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。

          指定一个字段或get/set方法映射到XML的属性。用于标注 Javabean 属性,用它标注的属性在映射后的 schema 中以元素属性形式表现

参数:name             指定属性名称,定制映射后的名称

         namespace    指定属性命名空间

         required         是否必须(默认为false,指定是否映射后的属性为必须出现的
例:


这个 Java 类在映射后的 Web 服务 schema 中会表现为:

9.@XmlTransient  定义某一字段或属性不需要被映射为XML。如,当一个类的XmlAccessorType 被标注为PROPERTY时,
在某一get/set方法的字段上标注此注解,那么该属性则不会被映射。

10.@XmlSchema 配置整个包的namespace,这个注解需放在package-info.java文件中。

 

三。JAXB基础---XML Schema
XML schema 是 XML 文档的格式定义,是 DTD 的替代产品用于约束 XML 文档内容及结构,比如它定义了 XML 文档可以出现的元素,
元素出现的顺序,元素具有的属性等。XML schema 本身就是一个 XML 文档,因此天然具有了 XML 的可扩展性。
同时 XML schema 对 XML 数据类型提供了更为丰富的支持。JAXB 框架的基础就是 XML schema,一个使用 JAXB 的典型场合就是根据业务数据模型
需要先写出 XML schema,然后利用 JAXB 框架的绑定编译器直接生成 XML 相应的 Java 类集。


四。JAXB与WEB服务的关系

JAX-WS 型 Web 服务将 XML 和 Java 之间的绑定代理给了 JAXB 来完成,也就是说在 Web 服务调用过程中的 XML 数据和 Java 对象间转换都是由 JAXB 框架来完成的。Web 服务中接口引用的参数、返回类型等等数据类型描述都是在关联的 XML schema 中定义的,而 JAXB 框架也正是根据这个 Web 服务关联的 XML schema 来完成于 Java 对象之间的相互映射。


从 Java 到 XML schema 的映射开发者可以通过 JAXB 提供的注解来完成,在编程 Java 类时可以使用 JAXB 丰富的注解轻松地完成绑定定制。

 

二.编译

JAXB使用简图
如图所示,使用JAXB分两步,首先利用xjc命令行程序编译DTD或Schema文件生成与XML数据结构相对应的JavaBeans类,再通过JAXB API中的marshal与unmarshal操作完成JavaBeans对象与XML数据之间的互换。
JAXB使用了最新的元数据技术,故而只能在JDK 1.5以上版本使用,JAXB的官方网站如下:
https://jaxb.dev.java.net/
可以在其中下载到最新的JAXB。安装之后的JAXB目录结构如下:

/JAXB-HOME(path/to/jaxb)
  /bin
  /lib
  /docs

在bin目录中有所有的JAXB工具,其中包括xjc命令行程序;在lib目录中可以找到所有JAXB的jar包;在docs目录中有一个JAXB的使用帮助及API说明。

一. xjc使用帮助

1. 通过命令行编译
命令行程序xjc用于编译DTD或Schema生成与XML数据结构对应的JavaBeans类。操作方法如下:

xjc [-xmlschema|-dtd] [–d 保存java文件的目录] [–p java文件所在的包] <编译文件>

-xmlschema  指定编译文件的格式为Schema格式,此参数是默认值,可以不用提供。
                    如果不提供此参数,编译文件必须是Schema文件。
-dtd  指定编译文件的格式为DTD格式,如果编译文件是DTD文件则必须提供此参数。
-d  指定了保存java文件的目录
-p  指定了生成的java文件所在的包

例如编译当前目录下的schema.xls文件,java文件保存在src目录,包名为generate,其命令如下:
xjc –d src –p generate schema.xsd
如果编译文件是schema.dta,则命令如下:
xjc –dtd –d src –p generate schema.dtd

 

2. 通过ANT编译
在/JAXB-HOME/lib目录中的jaxb-xjc.jar包中包含了XJCTask.class文件,可以依据该类定义一个ant task,通过执行该task生成java文件,task的定义如下:

 <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
   <classpath>
     <fileset dir="${JAXB-HOME}/lib" includes="*.jar" />
   </classpath>
 </taskdef>

执行xjc task的ant代码样例如下:

 <target name="generate" description="generate Java source files">
     <echo message="generate java from schema..." />
     <mkdir dir="src" />
     <xjc schema="books.xsd" package="com.chris.jaxb" destdir="gen-src">
         <produces dir="src/com/chris/jaxb " includes="**/*.java" />
     </xjc>
 </target>

其中
schema 指定DTD或Schema文件的位置;
destdir  指定生成的java文件所保存的根目录;
package  指定生成的java文件所在的包;
args  指定额外的参数,其中最重要的参数是“-dtd”,如果schema指定的是一个DTD文件,则args中必须提供“-dtd”;
produces  用于在指定目录中检查最新版本。

三.处理xml

实际案例:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<i>package jaxb.shop;

  

import java.util.Date;

import java.text.SimpleDateFormat;

  

import javax.xml.bind.annotation.adapters.XmlAdapter;

  

public class DateAdapter extends XmlAdapter<String, Date> {

  

    private String pattern = "yyyy-MM-dd HH:mm:ss";

    SimpleDateFormat fmt = new SimpleDateFormat(pattern);

      

    @Override

    public Date unmarshal(String dateStr) throws Exception {

          

        return fmt.parse(dateStr);

    }

  

    @Override

    public String marshal(Date date) throws Exception {

          

        return fmt.format(date);

    }

  

}

//用于格式化日期在xml中的显示格式,并且由xml unmarshal为java对象时,将字符串解析为Date对象</i>

在某个类中如下使用,解析出对应的时间格式.必须重载那2个方法,用于JAXB marshal xml,xml unmarshal object时候使用.

   @XmlJavaTypeAdapter(value=DateAdapter.class)
    private Date purDate;

9.但如果是和JPA一起使用的话,可以使用@Temporal(TemporalType.DATE)来格式时间,默认为TemporalType.TIMESTAMP类型.TemporalType属性如下:
public enum TemporalType {
    DATE, //java.sql.Date
    TIME, //java.sql.Time
    TIMESTAMP //java.sql.Timestamp
}

java.sql.Date
日期型,精确到年月日,例如“2008-08-08”
java.sql.Time
时间型,精确到时分秒,例如“20:00:00”
java.sql.Timestamp
时间戳,精确到纳秒,例如“2008-08-08 20:00:00.000000001”

 

10.在JAXB标准中,@XmlElementWrapper注解表示生成一个包装 XML 表示形式的包装器元素。 此元素主要用于生成一个包装集合的包装器 XML 元素。
注:@XmlElementWrapper仅允许出现在集合属性上。最后的案例将使用这个注解.

3. 最终案例(模拟XML--系统 --DB)

例子XML示例.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<?xml version="1.0" encoding="utf-8"?>

<userinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <id>110</id>

    <name>Credo</name>

    <address>China BeiJing</address>

    <job>programmer</job>

    <overinfos>

        <overinfo>

            <hobby>Accompany my girlfriend.</hobby>

            <!--开始日期 dateTime-->

            <beginDate>2009-06-02T12:00:00</beginDate>

            <!--结束日期 dateTime-->

            <endDate>2109-06-02T12:00:00</endDate>

        </overinfo>

        <overinfo>

            <hobby>Write some code.</hobby>

            <!--开始日期 dateTime-->

            <beginDate>2009-06-02T12:00:00</beginDate>

            <!--结束日期 dateTime-->

            <endDate>2029-06-02T12:00:00</endDate>

        </overinfo>

    </overinfos>

</userinfo>

Model层(JAXB+JPA):

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

package org.credo.jaxb.model;

import java.io.Serializable;

import java.util.List;

import javax.persistence.CascadeType;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.OneToMany;

import javax.persistence.Table;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlElementWrapper;

import javax.xml.bind.annotation.XmlElements;

import javax.xml.bind.annotation.XmlRootElement;

import org.hibernate.validator.constraints.Length;

/**

 * @author Credo

 */

@XmlRootElement

@XmlAccessorType(XmlAccessType.FIELD)

@Entity

@Table(name = "USERINFO")

public class Userinfo implements Serializable{

     

    private static final long serialVersionUID = 7870351249722416047L;

     

    @Id

    @Column(name = "ID", nullable = false)

    private Long id;

     

    @Column(name = "NAME", length = 50)

    @Length(max = 50)

    private String name;

     

    @Column(name = "ADDRESS", length = 50)

    @Length(max = 50)

    private String address;

     

    @Column(name = "JOB", length = 50)

    @Length(max = 50)

    private String job;

     

    @XmlElementWrapper(name = "overinfos")

    @OneToMany(cascade = CascadeType.ALL)

    @XmlElements(value = { @XmlElement(name = "overinfo", type = Overinfo.class) })

    private List<Overinfo> overinfos;

     

    public Long getId() {

        return id;

    }

    public void setId(Long id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getAddress() {

        return address;

    }

    public void setAddress(String address) {

        this.address = address;

    }

    public String getJob() {

        return job;

    }

    public void setJob(String job) {

        this.job = job;

    }

    public List<Overinfo> getOverinfos() {

        return overinfos;

    }

    public void setOverinfos(List<Overinfo> overinfos) {

        this.overinfos = overinfos;

    }

     

}

Overinfo.class

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

package org.credo.jaxb.model;

import java.io.Serializable;

import java.util.Date;

import javax.persistence.CascadeType;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

import javax.persistence.Table;

import javax.persistence.Temporal;

import javax.persistence.TemporalType;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlTransient;

import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "overinfo")

@Entity

@Table(name = "OVERINFO")

public class Overinfo implements Serializable {

    private static final long serialVersionUID = 2579971237985854291L;

    @XmlTransient

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    @Column(name = "ID")

    private Long id;

     

    @XmlTransient

    @ManyToOne(cascade = CascadeType.ALL)

    @JoinColumn(name = "UserinfoId")

    private Userinfo userinfo;

     

    @Column(name = "hobby", length = 20)

    private String hobby;

     

    @Temporal(TemporalType.DATE)

    @Column(name = "beginDate", length = 20)

    private Date beginDate;

     

    @Temporal(TemporalType.DATE)

    @Column(name = "endDate", length = 20)

    private Date endDate;

    public String getHobby() {

        return hobby;

    }

    public void setHobby(String hobby) {

        this.hobby = hobby;

    }

    public Date getBeginDate() {

        return beginDate;

    }

    public void setBeginDate(Date beginDate) {

        this.beginDate = beginDate;

    }

    public Date getEndDate() {

        return endDate;

    }

    public void setEndDate(Date endDate) {

        this.endDate = endDate;

    }

    public Long getId() {

        return id;

    }

    public void setId(Long id) {

        this.id = id;

    }

    public Userinfo getUserinfo() {

        return userinfo;

    }

    public void setUserinfo(Userinfo userinfo) {

        this.userinfo = userinfo;

    }

}

JAXB并发处理:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

package org.credo.jaxb;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.ConcurrentMap;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

public final class JAXBCache {

    private static final JAXBCache instance = new JAXBCache();

    private final ConcurrentMap<String, JAXBContext> contextCache = new ConcurrentHashMap<String, JAXBContext>();

    private JAXBCache() {

    }

    public static JAXBCache instance() {

        return instance;

    }

    JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {

        JAXBContext context = contextCache.get(clazz.getName());

        if ( context == null )

        {

            context = JAXBContext.newInstance(clazz);

            contextCache.putIfAbsent(clazz.getName(), context);

        }

        return context;

    }

}

JAXBExportSchema 导出JAXB的 class的 结构

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

package org.credo.jaxb;

import java.io.File;

import java.io.IOException;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.SchemaOutputResolver;

import javax.xml.transform.Result;

import javax.xml.transform.stream.StreamResult;

import org.credo.jaxb.model.Userinfo;

/**

 * JAXB 导出Schema。

 *

 * @author: Credo

 * @date: 2013-6-25

 */

public class JAXBExportSchema {

    public static void main(String[] args) {

        JAXBContext jct;

        try

        {

            jct = JAXBContext.newInstance(Userinfo.class);

            jct.generateSchema(new Resolver());

        }

        catch ( Exception ex )

        {

            ex.printStackTrace();

        }

    }

}

class Resolver extends SchemaOutputResolver {

    @Override

    public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {

        File file = new File("d:\\", suggestedFileName);

        StreamResult result = new StreamResult(file);

        result.setSystemId(file.toURI().toURL().toString());

        return result;

    }

}

JAXBUtil以及main方法测试:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

package org.credo.jaxb;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.util.ArrayList;

import java.util.List;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

import javax.xml.bind.Marshaller;

import javax.xml.bind.Unmarshaller;

import org.apache.commons.io.IOUtils;

import org.credo.jaxb.model.Overinfo;

import org.credo.jaxb.model.Userinfo;

/**

 * marshal对象和unmarshal对象都是由JAXBContext创建.所以一开始需要初始化JAXBContext.

 * @author Credo

 */

public class JAXBUtil {

    /**

     * 生成xml文件的二进制数据

     * @param obj 对象

     */

    public static byte[] marshal(Object obj) throws JAXBException {

        JAXBContext context = JAXBCache.instance().getJAXBContext(obj.getClass());

        Marshaller m = context.createMarshaller();

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        m.marshal(obj, outputStream);

        byte[] result = outputStream.toByteArray();

        return result;

    }

    /**

     * @param data xml stream

     * @param classe 类

     * @return jaxb生成xml的java 类对象

     */

    public static Object unmarshal(byte[] data, Class<?> classe) throws JAXBException {

        JAXBContext context = JAXBCache.instance().getJAXBContext(classe);

        Unmarshaller m = context.createUnmarshaller();

        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);

        Object obj = m.unmarshal(inputStream);

        return obj;

    }

    /**

     * @param data xml stream

     * @param classe 类

     * @return jaxb生成xml的java 类对象

     */

    public static Object unmarshal(InputStream in, Class<?> classe) throws JAXBException, IOException {

        JAXBContext context = JAXBCache.instance().getJAXBContext(classe);

        byte[] data = IOUtils.toByteArray(in);

        Unmarshaller m = context.createUnmarshaller();

        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);

        Object obj = m.unmarshal(inputStream);

        return obj;

    }

    public static void main(String[] args) throws JAXBException {

        Userinfo userinfo = new Userinfo();

        userinfo.setId(Long.valueOf(11));

        List<Overinfo> list = new ArrayList<Overinfo>();

        Overinfo e = new Overinfo();

        e.setHobby("陪女友");

        list.add(e);

        Overinfo e1 = new Overinfo();

        e1.setHobby("写代码");

        list.add(e1);

        userinfo.setOverinfos(list);

        byte[] b = JAXBUtil.marshal(userinfo);

        System.out.println(new String(b));

        userinfo = (Userinfo) JAXBUtil.unmarshal(b, Userinfo.class);

        System.out.println(userinfo.getOverinfos().get(0).getHobby());

    }

}

就不说明了,仔细看代码的,一会就明白了.不看的运行下也明白了.下面是上面main方法测试的输出结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<userinfo>
    <id>11</id>
    <overinfos>
        <overinfo>
            <hobby>陪女友</hobby>
        </overinfo>
        <overinfo>
            <hobby>写代码</hobby>
        </overinfo>
    </overinfos>
</userinfo>

陪女友

下面是使用JAXBExportSchema 导出JAXB的 class的 结构

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="userinfo" type="userinfo"/>

  <xs:complexType name="userinfo">

    <xs:sequence>

      <xs:element name="id" type="xs:long" minOccurs="0"/>

      <xs:element name="name" type="xs:string" minOccurs="0"/>

      <xs:element name="address" type="xs:string" minOccurs="0"/>

      <xs:element name="job" type="xs:string" minOccurs="0"/>

      <xs:element name="overinfos" minOccurs="0">

        <xs:complexType>

          <xs:sequence>

            <xs:element name="overinfo" type="overinfo" minOccurs="0" maxOccurs="unbounded"/>

          </xs:sequence>

        </xs:complexType>

      </xs:element>

    </xs:sequence>

  </xs:complexType>

  <xs:complexType name="overinfo">

    <xs:sequence>

      <xs:element name="hobby" type="xs:string" minOccurs="0"/>

      <xs:element name="beginDate" type="xs:dateTime" minOccurs="0"/>

      <xs:element name="endDate" type="xs:dateTime" minOccurs="0"/>

    </xs:sequence>

  </xs:complexType>

</xs:schema>

 

四.cxml

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值