파일 및 문자열로 저장하기 위한 간단한 XML 문서 빌더를 만들어 봅시다.
처음에 잘못된 소스 올려 수정했습니다.

------------------------------------------------------------------------------------------
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 간단히 XML 문서 생성하기
 * 간단한 형식의 XML 문서를 생성하기 위한 유틸성 클래스입니다.
 * 사용법은 XML 순서대로 Element와 Attribute를 등록해주면 되고, 순서에 맞지 않는 XML 문서의 정의는 지원하지 않습니다.
 *
 * 
 */
public class SimpleXMLBuilder {
    /** 최상위 문서 객체 */
    private Document doc;

    /** 마지막 추가한 Element의 부모 */
    private Element parent;

    /** 마지막에 추가한 Element */
    private Element element;

    /**
     * 생성자 : root element 받음
     * 
     * @param root
     * @throws ParserConfigurationException
     */
    public SimpleXMLBuilder(String root) throws ParserConfigurationException {
        doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        element = doc.createElement(root);
        parent = element;

        doc.appendChild( element );
    }

    /**
     * 현재 Element에 자식 Element 추가
     *
     * @param name
     */
    public void addSon(String name) {
        Element e = doc.createElement(name);
        element.appendChild(e);
        parent = element;
        element = e;
    }

    /**
     * 현재 부모 Element에 자식 Element 추가
     * 
     * @param name
     */
    public void addBrother(String name) {
        Element e = doc.createElement(name);
        parent.appendChild(e);
        element = e;
    }

    /**
     * 위치 이동
     *
     * @param deep 노드의 깊이
     * @param position 한 부모 노드에서의 형재 노드간의 위치
     * @throws Exception
     */
    public void move(int deep, int position) throws Exception {
        move(doc.getDocumentElement(), deep, position);
    }

    /**
     * 특정 노드로 부터의 위치 이동
     *
     * @param node 기준 노드
     * @param deep 노드의 깊이
     * @param position 한 부모 노드에서의 형재 노드간의 위치
     * @throws Exception
     */
    public void move(Node node, int deep, int position) throws Exception {
        Node n = node;
        for(int i=0; i<deep; i++) {
            if( n.getFirstChild() == null )
                throw new Exception("Can't move to deep " + deep);
            
            n = n.getFirstChild();
        }

        if( position > 0 ) {
            NodeList nodeList = n.getParentNode().getChildNodes();
            n = nodeList.item(position);
            if( n == null )
                throw new Exception("Can't move to position " + position);
        }

        element = (Element) n;
        if( n.getParentNode() != null )
            parent = (Element) n.getParentNode();
    }

    public void move(String expr) throws Exception {
        move(doc.getDocumentElement(), expr);
    }

    public void move(Node node, String expr) throws Exception {
        Node n = XPathAPI.selectSingleNode(node, expr);
        if( n == null )
            throw new Exception("Can't move to xpath expression " + expr);

        element = (Element) n;
        if( n.getParentNode() != null )
            parent = (Element) n.getParentNode();
    }

    /**
     * 마지막 추가한 Element에 속성 추가
     * 
     * @param name
     * @param value
     */
    public void setAttribute(String name, String value) {
        element.setAttribute(name, value);
    }

    /**
     * XML 문서를 문자열로 저장
     * 
     * @return
     * @throws IOException
     */
    public String saveToString() throws IOException {
        OutputFormat format = new OutputFormat();
        format.setIndenting(true);
        
        StringWriter out = new StringWriter();
        XMLSerializer serializer = new XMLSerializer(out, format);
        serializer.asDOMSerializer();
        serializer.serialize(doc.getDocumentElement());

        return out.toString();
    }

    /**
     * XML 문서를 File로 저장
     * 
     * @param filePath
     * @throws IOException
     */
    public void saveToFile(String filePath) throws IOException {
        File file = new File(filePath);
        if( file.exists() )
            throw new IOException("File already exists");

        OutputFormat format = new OutputFormat();
        format.setIndenting(true);

        FileWriter fw = new FileWriter(file);
        
        XMLSerializer serializer = new XMLSerializer(fw, format);
        serializer.asDOMSerializer();
        serializer.serialize(doc.getDocumentElement());

        fw.close();
    }

    public static void main(String[] args) {

        try {
            SimpleXMLBuilder xml = new SimpleXMLBuilder("애완동물");
            xml.addSon("조류");
            xml.addBrother("포유류");
            xml.addBrother("절지류");
            xml.addBrother("파충류");
            xml.addBrother("곤충류");

            // 계층 구조를 깊이와 위치로 이동하기
            xml.move(1, 0);
            xml.addSon("앵무새");
            xml.setAttribute("번호", "1");

            xml.addBrother("참새");
            xml.setAttribute("번호", "2");

            xml.addBrother("딱다구리");
            xml.setAttribute("번호", "3");

            xml.addBrother("부엉이");
            xml.setAttribute("번호", "4");

            // 계층 구조를 깊이와 위치로 이동하기
            xml.move(1, 0);
            xml.move(xml.element, 1, 1);

            xml.addSon("검참새");
            xml.addBrother("황참새");
            xml.addBrother("똥참새");

            // 계층 구조를 깊이와 위치로 이동하기
            xml.move(1, 1);
            xml.addSon("강아지");
            xml.setAttribute("번호", "1");

            xml.addBrother("고양이");
            xml.setAttribute("번호", "2");

            xml.addBrother("돼지");
            xml.setAttribute("번호", "3");

            // 계층 구조를 XPath 표현식으로 이동하기
            xml.move("/애완동물/포유류/고양이");
            xml.addSon("암고양이");
            xml.addBrother("숫고양이");

            System.out.println( xml.saveToString() );

        } catch(Exception e) {
            System.out.println(e);
        }

        
    }

+ Recent posts