Java解析和生成XML

1、Jaxb处理java对象和xml之间转换常用的annotation有:
  1. @XmlType
  1. @XmlElement
  1. @XmlRootElement
  1. @XmlAttribute
  1. @XmlAccessorType
  1. @XmlAccessorOrder
  1. @XmlTransient
  1. @XmlJavaTypeAdapter
2、常用annotation使用说明
@XmlType
  @XmlType用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。它有三个属性:name、propOrder、namespace,经常使用的只有前两个属性。如:
  
@XmlType(name = "basicStruct", propOrder = {
"intValue",
"stringArray",
"stringValue")
在使用@XmlType的propOrder 属性时,必须列出JavaBean对象中的所有属性,否则会报错。
  • @XmlElement
@XmlElement将Java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。如:
  @XmlElement(name="Address")  
  private String yourAddress;
 
@XmlRootElement
  • @XmlRootElement用于类级别的注解,对应xml的跟元素,常与 @XmlType 和 @XmlAccessorType一起使用。如:
  @XmlType
  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlRootElement
  public class Address {}
 
@XmlAttribute
@XmlAttribute用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。如:
  @XmlAttribute(name="Country")
  private String state;
 
@XmlAccessorType
@XmlAccessorType用于指定由java对象生成xml文件时对java对象属性的访问方式。常与@XmlRootElement、@XmlType一起使用。它的属性值是XmlAccessType的4个枚举值,分 别为:
  XmlAccessType.FIELD:java对象中的所有成员变量
  XmlAccessType.PROPERTY:java对象中所有通过getter/setter方式访问的成员变量
  XmlAccessType.PUBLIC_MEMBER:java对象中所有的public访问权限的成员变量和通过getter/setter方式访问的成员变量
  XmlAccessType.NONE:java对象的所有属性都不映射为xml的元素
  注意:@XmlAccessorType的默认访问级别是XmlAccessType.PUBLIC_MEMBER,因此,如果java对象中的private成员变量设置了public权限的getter/setter方法,就不要在   private变量上使用@XmlElement和@XmlAttribute注解,否则在由java对象生成xml时会报同一个属性在java类里存在两次的错误。同理,如果@XmlAccessorType的访问权限   为XmlAccessType.NONE,如果在java的成员变量上使用了@XmlElement或@XmlAttribute注解,这些成员变量依然可以映射到xml文件。
 
@XmlAccessorOrder
@XmlAccessorOrder用于对java对象生成的xml元素进行排序。它有两个属性值:
  AccessorOrder.ALPHABETICAL:对生成的xml元素按字母书序排序
  XmlAccessOrder.UNDEFINED:不排序
 
@XmlTransient
@XmlTransient用于标示在由java对象映射xml时,忽略此属性。即,在生成的xml文件中不出现此元素。
 
@XmlJavaTypeAdapter
@XmlJavaTypeAdapter常用在转换比较复杂的对象时,如map类型或者格式化日期等。使用此注解时,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。
  @XmlJavaTypeAdapter(value=xxx.class),value为自己定义的adapter类
  XmlAdapter如下:
public abstract class XmlAdapter<ValueType,BoundType> {
// Do-nothing constructor for the derived classes.
protected XmlAdapter() {}
// Convert a value type to a bound type.
public abstract BoundType unmarshal(ValueType v);
// Convert a bound type to a value type.
public abstract ValueType marshal(BoundType v);
}
3、示例
Shop.java
import java.io.FileReader;
import java.io.FileWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Set; import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorOrder;
import javax.xml.bind.annotation.XmlAccessOrder;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; //设置生成的xml的根节点的名称
@XmlRootElement(name = "shop")
//设置根据字段还是方法生成
@XmlAccessorType(XmlAccessType.FIELD)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
@XmlType(name = "shop", propOrder = { "name", "number", "describer", "address","orders" })
public class Shop { public static void main(String[] args) {
Set<Order> orders = new HashSet<Order>(); Address address1 = new Address("China", "ShangHai", "ShangHai", "Huang", "200000");
Customer customer1 = new Customer("Jim", "male", "13699990000", address1);
Order order1 = new Order("Mart", "LH59900", new Date(), new BigDecimal(60), 1);
order1.setCustomer(customer1); Address address2 = new Address("China", "JiangSu", "NanJing", "ZhongYangLu", "210000");
Customer customer2 = new Customer("David", "male", "13699991000", address2);
Order order2 = new Order("Mart", "LH59800", new Date(), new BigDecimal(80), 1);
order2.setCustomer(customer2); orders.add(order1);
orders.add(order2); Address address3 = new Address("China", "ZheJiang", "HangZhou", "XiHuRoad", "310000");
Shop shop = new Shop("CHMart", "100000", "EveryThing",address3);
shop.setOrders(orders); FileWriter writer = null;
try {
JAXBContext context = JAXBContext.newInstance(Shop.class);
Marshaller marshal = context.createMarshaller();
marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshal.marshal(shop, System.out); writer = new FileWriter("shop.xml");
marshal.marshal(shop, writer); Unmarshaller unmarshal = context.createUnmarshaller();
FileReader reader = new FileReader("shop.xml") ;
Shop shop1 = (Shop)unmarshal.unmarshal(reader); Set<Order> orders1 = shop1.getOrders();
for(Order order : orders1){
System.out.println("***************************");
System.out.println(order.getOrderNumber());
System.out.println(order.getCustomer().getName());
System.out.println("***************************");
} } catch (Exception e) {
e.printStackTrace();
} } @XmlAttribute
private String name; // @XmlElement
private String number; @XmlElement
private String describer; @XmlElementWrapper(name = "orders")
@XmlElement(name = "order")
private Set<Order> orders; @XmlElement
private Address address; public Shop() {
} public Shop(String name, String number, String describer, Address address) {
this.name = name;
this.number = number;
this.describer = describer;
this.address = address;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getNumber() {
return number;
} public void setNumber(String number) {
this.number = number;
} public String getDescriber() {
return describer;
} public void setDescriber(String describer) {
this.describer = describer;
} public Set<Order> getOrders() {
return orders;
} public void setOrders(Set<Order> orders) {
this.orders = orders;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
}
}

Order.java

import java.math.BigDecimal;
import java.util.Date; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlType(name="order",propOrder={"shopName","orderNumber","price","amount","purDate","customer"})
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Order {
private String shopName; @XmlAttribute
private String orderNumber; @XmlJavaTypeAdapter(value=DateAdapter.class)
private Date purDate; private BigDecimal price; private int amount; private Customer customer; public Order() {
} public Order(String shopName, String orderNumber, Date purDate,
BigDecimal price, int amount) {
this.shopName = shopName;
this.orderNumber = orderNumber;
this.purDate = purDate;
this.price = price;
this.amount = amount;
} public String getShopName() {
return shopName;
} public void setShopName(String shopName) {
this.shopName = shopName;
} public String getOrderNumber() {
return orderNumber;
} public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
} public Date getPurDate() {
return purDate;
} public void setPurDate(Date purDate) {
this.purDate = purDate;
} public BigDecimal getPrice() {
return price;
} public void setPrice(BigDecimal price) {
this.price = price;
} public int getAmount() {
return amount;
} public void setAmount(int amount) {
this.amount = amount;
} public Customer getCustomer() {
return customer;
} public void setCustomer(Customer customer) {
this.customer = customer;
} }

Customer.java

import java.util.Set;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; @XmlType
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Customer {
@XmlAttribute
private String name; private String gender; private String phoneNo; private Address address; private Set<Order> orders; public Customer() {
} public Customer(String name, String gender, String phoneNo, Address address) {
this.name = name;
this.gender = gender;
this.phoneNo = phoneNo;
this.address = address;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public String getPhoneNo() {
return phoneNo;
} public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} public Set<Order> getOrders() {
return orders;
} public void setOrders(Set<Order> orders) {
this.orders = orders;
} }

Address.java

import javax.xml.bind.annotation.XmlAccessorOrder;
import javax.xml.bind.annotation.XmlAccessOrder;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType; @XmlType(propOrder = { "state", "province", "city", "street", "zip" })
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class Address {
@XmlAttribute
private String state; @XmlElement
private String province; @XmlElement
private String city; @XmlElement
private String street; @XmlElement
private String zip; public Address() {
super();
} public Address(String state, String province, String city, String street,
String zip) {
super();
this.state = state;
this.province = province;
this.city = city;
this.street = street;
this.zip = zip;
} public String getState() {
return state;
} public void setState(String state) {
this.state = state;
} public String getProvince() {
return province;
} public void setProvince(String province) {
this.province = province;
} public String getCity() {
return city;
} public void setCity(String city) {
this.city = city;
} public String getStreet() {
return street;
} public void setStreet(String street) {
this.street = street;
} public String getZip() {
return zip;
} public void setZip(String zip) {
this.zip = zip;
} }

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<shop name="CHMart">
<number>100000</number>
<describer>EveryThing</describer>
<address state="China">
<province>ZheJiang</province>
<city>HangZhou</city>
<street>XiHuRoad</street>
<zip>310000</zip>
</address>
<orders>
<order orderNumber="LH59900">
<shopName>Mart</shopName>
<price>60</price>
<amount>1</amount>
<purDate>2016-11-23 14:51:40</purDate>
<customer name="Jim">
<gender>male</gender>
<phoneNo>13699990000</phoneNo>
<address state="China">
<province>ShangHai</province>
<city>ShangHai</city>
<street>Huang</street>
<zip>200000</zip>
</address>
</customer>
</order>
<order orderNumber="LH59800">
<shopName>Mart</shopName>
<price>80</price>
<amount>1</amount>
<purDate>2016-11-23 14:51:40</purDate>
<customer name="David">
<gender>male</gender>
<phoneNo>13699991000</phoneNo>
<address state="China">
<province>JiangSu</province>
<city>NanJing</city>
<street>ZhongYangLu</street>
<zip>210000</zip>
</address>
</customer>
</order>
</orders>
</shop>
***************************
LH59900
Jim
***************************
***************************
LH59800
David
**************************

工具类JaxbUtil.java:

import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName; import org.apache.commons.lang3.Validate; import com.thinkgem.jeesite.common.utils.Exceptions;
import com.thinkgem.jeesite.common.utils.Reflections;
import com.thinkgem.jeesite.common.utils.StringUtils;
/**
* 使用Jaxb2.0实现XML<->Java Object的Mapper.
* 在创建时需要设定所有需要序列化的Root对象的Class.
* 特别支持Root对象是Collection的情形.
*/
public class JaxbUtil {
private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();
/**
* Java Object->Xml without encoding.
*/
@SuppressWarnings("rawtypes")
public static String toXml(Object root) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, null);
} /**
* Java Object->Xml with encoding.
*/
@SuppressWarnings("rawtypes")
public static String toXml(Object root, String encoding) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, encoding);
} /**
* Java Object->Xml with encoding.
*/
@SuppressWarnings("rawtypes")
public static String toXml(Object root, Class clazz, String encoding) {
try {
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(root, writer);
return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
} /**
* Java Collection->Xml without encoding, 特别支持Root Element是Collection的情形.
*/
@SuppressWarnings("rawtypes")
public static String toXml(Collection<?> root, String rootName, Class clazz) {
return toXml(root, rootName, clazz, null);
} /**
* Java Collection->Xml with encoding, 特别支持Root Element是Collection的情形.
*/
@SuppressWarnings("rawtypes")
public static String toXml(Collection<?> root, String rootName, Class clazz, String encoding) {
try {
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.collection = root; JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrapper>(new QName(rootName),
CollectionWrapper.class, wrapper); StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(wrapperElement, writer); return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
} /**
* Xml->Java Object.
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(String xml, Class<T> clazz) {
try {
StringReader reader = new StringReader(xml);
return (T) createUnmarshaller(clazz).unmarshal(reader);
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
} /**
* 创建Marshaller并设定encoding(可为null).
* 线程不安全,需要每次创建或pooling。
*/
@SuppressWarnings("rawtypes")
public static Marshaller createMarshaller(Class clazz, String encoding) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}
return marshaller;
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
} /**
* 创建UnMarshaller.
* 线程不安全,需要每次创建或pooling。
*/
@SuppressWarnings("rawtypes")
public static Unmarshaller createUnmarshaller(Class clazz) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
} @SuppressWarnings("rawtypes")
protected static JAXBContext getJaxbContext(Class clazz) {
Validate.notNull(clazz, "'clazz' must not be null");
JAXBContext jaxbContext = jaxbContexts.get(clazz);
if (jaxbContext == null) {
try {
jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
jaxbContexts.putIfAbsent(clazz, jaxbContext);
} catch (JAXBException ex) {
throw new RuntimeException("Could not instantiate JAXBContext for class [" + clazz + "]: "
+ ex.getMessage(), ex);
}
}
return jaxbContext;
} /**
* 封装Root Element 是 Collection的情况.
*/
public static class CollectionWrapper { @XmlAnyElement
protected Collection<?> collection;
}
}

测试:

String s = JaxbUtil.toXml(shop);
System.out.println(s);

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<shop name="CHMart">
<number>100000</number>
<describer>EveryThing</describer>
<address state="China">
<province>ZheJiang</province>
<city>HangZhou</city>
<street>XiHuRoad</street>
<zip>310000</zip>
</address>
<orders>
<order orderNumber="LH59800">
<shopName>Mart</shopName>
<price>80</price>
<amount>1</amount>
<purDate>2016-11-23 14:54:39</purDate>
<customer name="David">
<gender>male</gender>
<phoneNo>13699991000</phoneNo>
<address state="China">
<province>JiangSu</province>
<city>NanJing</city>
<street>ZhongYangLu</street>
<zip>210000</zip>
</address>
</customer>
</order>
<order orderNumber="LH59900">
<shopName>Mart</shopName>
<price>60</price>
<amount>1</amount>
<purDate>2016-11-23 14:54:39</purDate>
<customer name="Jim">
<gender>male</gender>
<phoneNo>13699990000</phoneNo>
<address state="China">
<province>ShangHai</province>
<city>ShangHai</city>
<street>Huang</street>
<zip>200000</zip>
</address>
</customer>
</order>
</orders>
</shop>
上一篇:UVA 10801 Lift Hopping 电梯换乘(最短路,变形)


下一篇:杭电oj 3361