xstream学习小结

来源:互联网 发布:3ds港版淘宝哪家店好 编辑:程序博客网 时间:2024/04/30 10:22
    在XML跟普通POJO的序列化过程中,有很多的方法,其中发现xstream这个包还是不错的,它的作者是大名鼎鼎的thoughtworks写的,下面简单分析下。

1 首先是POJO对象,比如:
   public class Employee {
private String name;
private String designation;
private String department;
  。。。。。。。。。。

2 把POJO变成XML对象
  XStream xstream=new XStream(new DomDriver());
   xstream.alias("employee",Employee.class);
  strxml=xstream.toXML(person);
  System.out.println(strxml);

3 把XML对象反序列化为POJO对象
   String str="....."//XML
  Employee employee=(Employee)xstream.fromXML(str);
  System.out.println("姓名:"+employee.getName());
4 另外附上一个比较复杂的精彩例子:
   public class XmlParser {
private static final Log log = LogFactory.getLog(XmlParser.class);

private static final String DEFAULT_ENCODING = "UTF-8";

/**
* 获取 XML 文件头 encoding 中指定字符集的查询匹配器。
*/
private static Pattern encodingPattern = Pattern.compile("<\\?xml.*\\s+encoding\\s*=\\s*[\"']?([\\w\\-_]+)[\"'\\s?><]", Pattern.DOTALL + Pattern.CASE_INSENSITIVE);

private static CustomXppDriver driver = new CustomXppDriver(new CustomReplacer());

private static boolean flat;

private static boolean notList;

/**
* 将 XML 文件解析为 Map 集合数据,使用 XML 内容指定的字符集进行编码解析,若 XML 中未指定编码,则默认使用 UTF-8 进行编码解析。
*/
public static Map parseXmlFile(String fileName) throws FileNotFoundException, UnsupportedEncodingException {
return parse(new File(fileName));
}

/**
* 将 XML 文件解析为 Map 集合数据,使用 XML 内容指定的字符集进行编码解析,若 XML 中未指定编码,则默认使用 UTF-8 进行编码解析。
*/
public static Map parse(File xmlFile) throws FileNotFoundException, UnsupportedEncodingException {
Reader reader = null;
try {
reader = getXmlEncodingReader(new FileInputStream(xmlFile));
return parse(reader);
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception ignore) {
}
}
}
}

/**
* 将 XML 字节数组解析为 Map 集合数据,使用 XML 内容指定的字符集进行编码解析,若 XML 中未指定编码,则默认使用 UTF-8 进行编码解析。
*/
public static Map parse(byte[] xmlBytes) throws UnsupportedEncodingException {
return parse(getXmlEncodingReader(new ByteArrayInputStream(xmlBytes)));
}

/**
* 将 XML 字节数组,按照指定字符集解析为 Map 集合数据。
*/
public static Map parse(byte[] xmlBytes, String encoding) throws UnsupportedEncodingException {
HierarchicalStreamReader reader = driver.createReader(new ByteArrayInputStream(xmlBytes), encoding);
return getData(reader);
}

/**
* 将 XML 字符串,解析为 Map 集合数据。
* @param xmlStr 字符串
* @return 集合数据
*/
public static Map parse(String xmlStr) {
return parse(new StringReader(xmlStr));
}

/**
* 将 XML 字节流,解析为 Map 集合数据,使用 XML 内容指定的字符集进行编码解析 */
public static Map parse(InputStream xmlStream) throws UnsupportedEncodingException {
return parse(getXmlEncodingReader(xmlStream));
}

/**
* 将 XML 字节流,按照指定字符集解析为 Map 集合数据。
* @param xmlStream 字节流
* @param encoding 字符集
* @return 集合数据
* @throws UnsupportedEncodingException 不支持的字符集异常
*/
public static Map parse(InputStream xmlStream, String encoding) throws UnsupportedEncodingException {
HierarchicalStreamReader reader = driver.createReader(xmlStream, encoding);
return getData(reader);
}
/**
* 将 XML 字符流,解析为 Map 集合数据。
* @param xmlReader 字符流
* @return 集合数据
*/
public static Map parse(Reader xmlReader) {
HierarchicalStreamReader reader = driver.createReader(xmlReader);
return getData(reader);
}

/**
* 获取字节流中 XML 内容指定的字符集编码,若 XML 中未指定编码,则返回 UTF-8。
* @param stream 字节流,必须支持 mark/reset 方法。
* @return 字符集
*/
public static String getEncoding(InputStream stream) {
String encoding = DEFAULT_ENCODING;
if (!stream.markSupported()) {
return encoding;
}
byte[] buf = new byte[70];
try {
stream.mark(100);
int len = stream.read(buf);
if (len  > 0) {
String xmlHead = new String(buf, 0, len);
Matcher m = encodingPattern.matcher(xmlHead);
if (m.find()) {
encoding = m.group(1).trim();
}
}
stream.reset();
} catch (Throwable e) {
log.error("get xml encoding error!", e);
}
return encoding;
}

/**
* 将 XML 字节流,转换为支持 XML 内容指定编码的字符流,若 XML 中未指定编码,则默认使用 UTF-8 进行编码解析。
* @param stream 字节流
* @return 字符流
* @throws UnsupportedEncodingException 不支持的字符集异常
*/
private static Reader getXmlEncodingReader(InputStream stream) throws UnsupportedEncodingException {
stream = new BufferedInputStream(stream);
return new InputStreamReader(stream, getEncoding(stream));
}

/**
* 将 XML 字符流,解析为 Map 集合数据。
* @param reader XML 字符流读取对象
* @return 集合数据
*/
private static Map getData(HierarchicalStreamReader reader) {
Map data = new HashMap();
fillData(reader, data, flat);
return data;
}

/**
* 设置解析完成后,填充Map集合时是否采用集合的方法。默认采用集合方法。
* 集合:既XML节点名称相同的数据使用ArrayList集合进行存储。
* 单一:既XML节点名称相同的数据只取第一个值进行存储。
* @param notList
*/
public static void setNotList(boolean no){
notList = no;
}

public static boolean isNotList(){
return notList;
}

/**
* 设置解析完成后,是否采取平板填充模式填充 Map 集合。若不采用平板填充模式,则 Map 集合采用与 XML 节点级别相同的结构存储数据。默认不采用。
* 平板填充模式:即不论是 XML 的哪级节点数据,均填充到根集合中,若根集合已存在该名称的节点数据,则此节点名称的数据采用 List 对象顺序存储。
* @param flatType 是否采取平板填充模式。
*/
public static void setFlatType(boolean flatType) {
flat = flatType;
}

/**
* 是否采取平板填充模式填充 Map 集合?
* @return 是否采取平板填充模式。
*/
public static boolean isFlatType() {
return flat;
}

/**
* 解析 XML 字符流,并将数据填充到指定 Map 集合中。
* @param reader XML 字符流读取对象
* @param data 待填充数据集合
* @param flatType 是否采用平板填充模式
*/
private static void fillData(HierarchicalStreamReader reader, Map data, boolean flatType) {
Map childs;

String name = reader.getNodeName();
Object value;
if (!reader.hasMoreChildren()) {
value = reader.getValue();
childs = null;
} else if (!flatType) {
value = childs = new HashMap();
} else {
value = "";
childs = data;
}
Object nodeContainer = data.get(name);
//name名称重复的直接覆盖
if(notList){
if (nodeContainer == null) {
if (value != null) {
data.put(name, value);
}
}
}else{
//重复的生成list保存
if (nodeContainer == null) {
if (value != null) {
data.put(name, value);
}
} else if (nodeContainer instanceof ArrayList) {
((ArrayList)nodeContainer).add(value);
} else {
ArrayList nodeList = new ArrayList();
nodeList.add(nodeContainer);
nodeList.add(value);
data.put(name, nodeList);
}
}
while (reader.hasMoreChildren()) {
reader.moveDown();
fillData(reader, childs, flatType);
reader.moveUp();
}
}

/**
* 自定义 XPP 解析驱动类
* @author wd
*/
private static class CustomXppDriver extends XppDriver {
    public CustomXppDriver() {
        super(new CustomReplacer());
    }
    public CustomXppDriver(XmlFriendlyReplacer replacer) {
        super(replacer);
    }
    /**
     * 将 XML 字节流,转换为支持指定字符集编码的 XML 字符流读取对象。
     * @param stream 字节流
     * @param encoding 字符集
     * @return XML 字符流读取对象
     * @throws UnsupportedEncodingException 不支持的字符集异常
     */
    public HierarchicalStreamReader createReader(InputStream stream, String encoding) throws UnsupportedEncodingException {
        return createReader(new InputStreamReader(stream, encoding));
    }
}

/**
* 自定义 XML 标签转换类
* @author wd
*/
private static class CustomReplacer extends XmlFriendlyReplacer {
public String escapeName(String name) {
return name;
}

public String unescapeName(String name) {
return name;
}
}

public static void main(String[] args) throws Exception {
java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream();
java.io.FileInputStream input = null;
byte[] data = new byte[1024];
int len = -1;
try {
input = new java.io.FileInputStream("c:\\test.txt");
for (;(len = input.read(data)) >= 0;) {
output.write(data, 0, len);
}
} catch (Exception e) {
throw e;
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
}
}
}
byte[] xmlBytes = getMsg(output.toString());
System.out.println("xml 内容=" + new String(xmlBytes, getEncoding(new java.io.ByteArrayInputStream(xmlBytes))));
XmlParser.setFlatType(true);
Map xml = XmlParser.parse(xmlBytes);
System.out.println();
System.out.println("xml 对象=" + xml);
}
原创粉丝点击