http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://blog.600km.xyz/2015/12/22/java-xml-by-dom/
- Identify the unmappable class
- Create an equivalent class that is mappable
- Create an XmlAdapter to convert between unmappable and mappable objects
- Specify the XmlAdapter
public
class
MyMapType {
public
List<MyMapEntryType> entry =
new
ArrayList<MyMapEntryType>();
}
public
class
MyMapEntryType {
@XmlAttribute
public
Integer key;
@XmlValue
public
String value;
}
public
final
class
MyMapAdapter
extends
XmlAdapter<MyMapType,Map<Integer, String>> {
@Override
public
MyMapType marshal(Map<Integer, String> arg0)
throws
Exception {
MyMapType myMapType =
new
MyMapType();
for
(Entry<Integer, String> entry : arg0.entrySet()) {
MyMapEntryType myMapEntryType =
new
MyMapEntryType();
myMapEntryType.key = entry.getKey();
myMapEntryType.value = entry.getValue();
myMapType.entry.add(myMapEntryType);
}
return
myMapType;
}
@Override
public
Map<Integer, String> unmarshal(MyMapType arg0)
throws
Exception {
HashMap<Integer, String> hashMap =
new
HashMap<Integer, String>();
for
(MyMapEntryType myEntryType : arg0.entry) {
hashMap.put(myEntryType.key, myEntryType.value);
}
return
hashMap;
}
}
@XmlRootElement
@XmlAccessorType
(XmlAccessType.FIELD)
public
class
Foo {
@XmlJavaTypeAdapter
(MyMapAdapter.
class
)
Map<Integer, String> map =
new
HashMap<Integer, String>();
dom
DOM是W3C处理XML的标准API,多种语言都实现了该标准,java对dom的实现在org.w3c.dom包内。很多工具类都是在此基础上进行了封装和扩充,如jdom、dom4j等,这里使用原生实现来完成对xml文档的基本操作。
DOM的实现原理是将XML作为树结构全部读入内存,再进行操作。好处是简单快捷,可以修改结构和数据,而造成的隐患则是是在读取大型XML文件时,可能会造成过多的内存占用。
DOM的实现原理是将XML作为树结构全部读入内存,再进行操作。好处是简单快捷,可以修改结构和数据,而造成的隐患则是是在读取大型XML文件时,可能会造成过多的内存占用。
public class XmlParser {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
public Document parseDoc(String filePath) {
Document document = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(new File(filePath));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public static void main(String[] args) {
XmlParser parser = new XmlParser();
Document document = parser.parseDoc("D://shopping.xml");
Element rootElement = document.getDocumentElement();
List<Goods> goodsList = new ArrayList<Goods>();
NodeList goodsNodeList = rootElement.getElementsByTagName("goods");
for (int i = 0; i < goodsNodeList.getLength(); i++) {
Element child = (Element) goodsNodeList.item(i);
Goods goods = new Goods(child);
goodsList.add(goods);
}
// NodeList goodsNodeList = rootElement.getChildNodes();
// for (int i = 0; i < goodsNodeList.getLength(); i++) {
// Node node = goodsNodeList.item(i);
// if (node.getNodeType() == Node.ELEMENT_NODE) {
// Element child = (Element) node;
// Goods goods = new Goods(child);
// goodsList.add(goods);
// }
// }
float total = 0;
int sum = 0;
for (Goods goods : goodsList) {
total += goods.getTotal();
sum += goods.getNumber();
}
System.out.println(total);
System.out.println(sum);
}
static class Goods {
private float price;
private int number;
public Goods(Element element) {
this.price = Float.parseFloat(element.getElementsByTagName("price").item(0).getTextContent());
this.number = Integer.parseInt(element.getElementsByTagName("number").item(0).getTextContent());
}
public float getTotal(){
return this.price * this.number;
}
public int getNumber(){
return number;
}
}
}
node和element的关系
element一定是node但是node不一定是element,node可能是元素节点、属性节点、文本节点,而element表示包含开始标签和结束标签的完整元素。
所以上面的代码中 用
所以上面的代码中 用
NodeList goodsNodeList = rootElement.getElementsByTagName("goods");
获取了NodeList,可以直接转型为Element: Element child = (Element) node;
如果获取的是node节点
如果获取的是node节点
NodeList goodsNodeList = rootElement.getChildNodes();
则必须在循环中增加判断if (node.getNodeType() == Node.ELEMENT_NODE) {} 判断当前节点是否为Element元素。
生成xml文件
将统计后的订单信息以xml格式输出,生成文件格式如下
<?xml version="1.0" encoding="utf-8"?>
<order>
<total>15.6</total>
<sums>7</sums>
</order>
生成xml的操作和读取的顺序类似,先创建rootElement,然后添加childElement,再将rootElement放到document中,最后通过io输出xml文件到指定路径。
public class XmlParser {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
public Document parseDoc(String filePath) {
Document document = null;
try {
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
document = builder.parse(new File(filePath));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public void generateXml(String filePath, Document document){
DOMSource source = new DOMSource(document);
Transformer transformer = createtransformer();
PrintWriter pw = null;
try {
pw = new PrintWriter(new FileOutputStream(filePath));
StreamResult result = new StreamResult(pw);
transformer.transform(source, result);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e1) {
e1.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
} finally {
pw.close();
}
}
public Document createDoc() {
Document document = null;
try {
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
document = builder.newDocument();
document.setXmlStandalone(true);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
return document;
}
public Transformer createtransformer(){
Transformer transformer = null;
try {
transformer = transformerFactory.newTransformer();
//default former
// transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
return transformer;
}
public static void main(String[] args) {
XmlParser parser = new XmlParser();
Document document = parser.parseDoc("D://shopping.xml");
Element rootElement = document.getDocumentElement();
List<Goods> goodsList = new ArrayList<Goods>();
NodeList goodsNodeList = rootElement.getElementsByTagName("goods");
for (int i = 0; i < goodsNodeList.getLength(); i++) {
Element child = (Element) goodsNodeList.item(i);
Goods goods = new Goods(child);
goodsList.add(goods);
}
float total = 0;
int sum = 0;
for (Goods goods : goodsList) {
total += goods.getTotal();
sum += goods.getNumber();
}
Document orderDocument = parser.createDoc();
Order order = new Order(total, sum);
Element orderElement = order.getElement(orderDocument);
orderDocument.appendChild(orderElement);
parser.generateXml("D://order.xml", orderDocument);
}
static class Order {
private float total = 0;
private int sum = 0;
public Order(float total, int sum) {
this.total = total;
this.sum = sum;
}
public Element getElement(Document document) {
Element rootElement = document.createElement("order");
Element totalElement = document.createElement("total");
totalElement.setTextContent(String.valueOf(this.total));
rootElement.appendChild(totalElement);
Element sumElement = document.createElement("sum");
sumElement.setTextContent(String.valueOf(this.sum));
rootElement.appendChild(sumElement);
return rootElement;
}
}
static class Goods {
private float price;
private int number;
public Goods(Element element) {
this.price = Float.parseFloat(element.getElementsByTagName("price").item(0).getTextContent());
this.number = Integer.parseInt(element.getElementsByTagName("number").item(0).getTextContent());
}
public float getTotal() {
return this.price * this.number;
}
public int getNumber() {
return number;
}
}
}
-- the generate xml logic doesn't belong to domain classes.
standalone
这里有一个小坑 就是生成的xml中有一个属性为standalone=”no”
standalone表示是否为独立文件,也就是说是否依赖于其他外部文件,如果为yes,则表示为不依赖其他外部文件的独立文件,默认为yes。
但是生成之后的standalone=”no”,不符合预期,并且
standalone表示是否为独立文件,也就是说是否依赖于其他外部文件,如果为yes,则表示为不依赖其他外部文件的独立文件,默认为yes。
但是生成之后的standalone=”no”,不符合预期,并且
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
设置格式之后standalone=”no”仍然为no。这时需要设置document中的setXmlStandalone属性,
document.setXmlStandalone(true);
再次输出,可以去掉standalone属性。