Friday, December 25, 2015

Java XML



http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html
  1. Identify the unmappable class
  2. Create an equivalent class that is mappable
  3. Create an XmlAdapter to convert between unmappable and mappable objects
  4. Specify the XmlAdapter
Map could be represented by an object (MyMapType), that contained a list of objects with two properties: key and value (MyMapEntryType). 
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>();
http://blog.600km.xyz/2015/12/22/java-xml-by-dom/

dom

DOM是W3C处理XML的标准API,多种语言都实现了该标准,java对dom的实现在org.w3c.dom包内。很多工具类都是在此基础上进行了封装和扩充,如jdom、dom4j等,这里使用原生实现来完成对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节点
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”,不符合预期,并且
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
设置格式之后standalone=”no”仍然为no。这时需要设置document中的setXmlStandalone属性,
document.setXmlStandalone(true);
再次输出,可以去掉standalone属性。


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts