[Java] Xml파서로 xPath형식으로 xml작성하기


Development note/Java  2015. 2. 15. 22:50

안녕하세요.. 명월입니다.


이번 포스팅에서는 저번 포스팅에 이어서 읽어드리는 것이 아니고 xml을 만드는 모듈을 만들어 보겠습니다..

이 부분도 역시 JAVA api가 있는데 저는 만들어 버렸네요… 보통 표준 모듈이라하면 API를 이용하는게 더 버그가 줄겠지만 만들어 쓰게 되면 이런저런 응용이 가능하겠습니다.

먼저 소스를 부분입니다.

import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XMLWriter extends XMLReader{

  protected XMLWriter(){ super(); }
  protected XMLWriter(String path) throws Exception{ 
    super(path);
  }
  public static XMLWriter getInstance(String path) throws Exception{
    return new XMLWriter(path);
  }
  @Override
  protected void initialize(String path)throws Exception{
    setDocument(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
    setFile(path);
  }
  public void setValue(String xpath,String value) throws Exception{
    ArrayList<String> pathNode = PathSplite(xpath);
    NodeList nodeList = null;
    Element element = null;
    NodeType type = null;
    for(int i=0 ; i < pathNode.size() ; i++){
      type = NodeTypeCheck(pathNode.get(i));
      if(type.equals(NodeType.NODE)){
        element = NodeCreate(element,nodeList,pathNode.get(i),0,(i == pathNode.size()-1)?value:null);
      }else if(type.equals(NodeType.LIST)){
        String pNodeName = pathNode.get(i);
        int sPos = pNodeName.indexOf("[")+1;
        int ePos = pNodeName.indexOf("]");
        int listIndex = Integer.valueOf(pNodeName.substring(sPos,ePos)) - 1;
        pNodeName = pNodeName.substring(0,sPos-1);
        element = NodeCreate(element,nodeList,pNodeName,listIndex,(i == pathNode.size()-1)?value:null);
      }else{
        if((i == pathNode.size()-1)){
          String attrName = pathNode.get(pathNode.size()-1).substring(1);
          element.removeAttribute(attrName);
          element.setAttribute(attrName, value);
        }else{
          throw new Exception("Pathの表現が非性格です。- ErrorCode : setValue");
        }
      }
    }
    flush();
  }
  protected Element NodeCreate(Element element,NodeList nodeList,String pNodeName,int count,String value){
    Element buffer = null;
    if(element == null){
      nodeList = getDocument().getElementsByTagName(pNodeName);
    }else{
      nodeList = element.getElementsByTagName(pNodeName);
    }
    int length = nodeList.getLength();
    for(int j=0;j<=count;j++){
      if(length <= j){
        buffer = getDocument().createElement(pNodeName);
        if(element == null){
          getDocument().appendChild(buffer);
        }else{
          element.appendChild(buffer);
        }
      }
    }
    if(element == null){
      nodeList = getDocument().getElementsByTagName(pNodeName);
    }else{
      nodeList = element.getElementsByTagName(pNodeName);
    }
    buffer = (Element)nodeList.item(count);
    if(value != null){
      NodeList childnodes = buffer.getChildNodes();
      for(int z=0 ; z < childnodes.getLength() ; z++){
        if(buffer.getChildNodes().item(z).getNodeType() == Node.TEXT_NODE){
          buffer.removeChild(buffer.getChildNodes().item(z));
        }
      }
      buffer.appendChild(getDocument().createTextNode(value));
    }
    return buffer;
  }
  protected ArrayList<String> PathSplite(String path) throws Exception{
    String[] pathNode = path.split("/");
    if(pathNode.length <= 1){
      throw new Exception("Pathの表現が非性格です。- ErrorCode : PathSplite");
    }
    ArrayList<String> ret = new ArrayList<String>();
    for(int i=1 ; i < pathNode.length ; i++){
      ret.add(pathNode[i]);
    }
    return ret;
  }
  protected NodeType NodeTypeCheck(String nodeName){
    if(nodeName.indexOf("@") >= 0){
      return NodeType.ATTRIBUTE;
    }else if(nodeName.indexOf("[") >= 0 && nodeName.indexOf("]") >= 0){
      return NodeType.LIST;
    }else{
      return NodeType.NODE;
    }
  }
  public void flush() throws Exception{
    try {
      TransformerFactory.newInstance().newTransformer().transform(new DOMSource(getDocument()), new StreamResult(getFile()));
      getDocument().getDocumentElement().normalize();
    } catch (Exception e) {
      throw new Exception("error");
    }
  }
}

소스 설명입니다.

먼저 클래스는 전의 Reader를 상속 받아서 쓰겠습니다. New 부분은 protected로 해서 new로 선언을 못하게 막고 Instance로 취득 가능하게 작성하겠습니다.

getInstance를 부르게 되면 Overide된 initialize가 호출 되어 초기화가 되곘습니다.

외부에서는 setValue를 호출하게 되어 Node를 작성하고 최종적으로 flush를 호출하게 되어 XML이 작성되곘습니다.

위 소스로 테스트를 해보곘습니다.

원하는 결과가 나왔습니다.

startMain.java

XMLReader.java

XMLWriter.java