Java에서 XML을 다루기 위한 API들입니다. DOM, SAX, JDOM,StAX
IBM의 developerworks에 보면 좋은 tutorial이 있습니다.
XML 입문(한글) :
http://www.ibm.com/developerworks/kr/xml/newto/
참고자료를 보면서 간단하게 정리한 내용은..
DOM(document object model) :
object-based(객체기반) 으로 트리구조를 이루며 XML 내용을 모두 분석하므로 느리고 메모리 사용이 많음
SAX(simple api for xml) :
event-based(이벤트 기반) 으로 순차적으로 읽기만 가능하며 DOM에 비해 빠르고 메모리 사용 적음
JDOM(java document object model)
object-based(객체기반)으로 DOM을 Java에 친숙하게 개량하고 DOM,SAX와의 상호 연동 지원
StAX(streaming api for xml)
cursor-based(커서 기반)으로 DOM, SAX를 보안한 방법으로 필요할때 정보를 추출
입니다.
다음은 DOM, SAX, StAX에 대한 장단점입니다.
(원본 출처가 oracle magazine이었는데 갈무리한 blog를 까먹었네요.)
□ XML 구문 분석 기술 요약
ㅁ 장점
+-------------------------------------------------------------------------------------------------
|DOM |* 사용 편의성
| |* 편리한 탐색을 위한 풍부한 API 집합
| |* 전체 트리가 메모리로 로드되므로 XML 문서에 대한 임의 액세스 허용
+---------------------------------------------------------------------------------------
|SAX |* 전체 문서가 메모리에 로드되지 않으므로 메모리 소비량 감소
| |* 여러 ContentHandler를 등록할 수 있는 푸시 모델
+---------------------------------------------------------------------------------------
|StAX |* 편의성과 성능을 위한 두 개의 구문 분석 모델이 포함되어 있음
| |* 애플리케이션이 구문 분석을 제어하므로 여러 입력이 더 쉽게 지원됨
| |* 효율적인 데이타 검색을 가능하게 하는 강력한 필터링 기능 제공
+---------------------------------------------------------------------------------------
ㅁ 단점
+---------------------------------------------------------------------------------------
|DOM |* 한 번에 구문 분석해야 함
| |* 전체 트리를 메모리로 로드하는 경우 과도한 부담 발생
| |* 객체 유형 바인딩의 경우 일반 DOM 노드가 적합하지 않음
| | (모든 노드에 대한 객체 작성 필요)
+---------------------------------------------------------------------------------------
|SAX |* 내장된 문서 탐색 지원 없음
| |* XML 문서에 대한 임의 액세스 없음
| |* XML 수정에 대한 지원 없음
| |* 이름 공간 범위 지정에 대한 지원 없음
+---------------------------------------------------------------------------------------
|StAX |* 내장된 문서 탐색 지원 없음
| |* XML 문서에 대한 임의 액세스 없음
| |* XML 수정에 대한 지원 없음
+---------------------------------------------------------------------------------------
ㅁ 가장 적합한 경우
+---------------------------------------------------------------------------------------
|DOM |* XML 문서를 수정해야 하거나 XSLT를 위한 애플리케이션
| | (읽기 전용 XML 애플리케이션에는 사용되지 않음)
+---------------------------------------------------------------------------------------
|SAX |* XML에서 읽기만 수행하는 애플리케이션
| | (XML 문서 조작 또는 수정에는 사용되지 않음)
+---------------------------------------------------------------------------------------
|StAX |* 스트리밍 모델과 네임 스페이스에 대한 지원이 필요한 애플리케이션
| | (XML 문서 조작 또는 수정에는 사용되지 않음)
+---------------------------------------------------------------------------------------
이후 소스들은 참고자료를 보면서 따라해본 소스들이며 JDK 5에서 테스트 하였으며
샘플로 사용한 xml 파일은 상당히 단순합니다.
xml 샘플파일 a.xml xml 샘플파일 a.xml
a.xml
<?xml version="1.0" encoding="UTF-8"?>
<?Test factor="888" ?>
<orders xmlns="http://www.test.com/test.html" attr1="attr1" value="hi">
<order>
<customerid limit="1000">
12341
<creditRating>good</creditRating>
</customerid>
<status>pending</status>
<item instock="Y" itemid="SA15">
<name>Silver Show Saddle, 16 inch</name>
<price>825.00</price>
<qty>1</qty>
</item>
<testA/>
</order>
</orders>
xml 샘플파일 a.xml
DOM 사용
DOM을 사용하여 XML 을 읽어 전체 읽기, 수정, 삭제, 다시 XML 파일로 저장의 작업 샘플입니다.
"Understanding DOM :
http://www.ibm.com/developerworks/edu/x-dw-xudom-i.html " 를 보면서 따라한 샘플입니다.
DOM 샘플 : DOM.java DOM 샘플 : DOM.java
DOM.java
package compress;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class DOM {
public static void main(String[] args) {
try {
/*
* DOM 기본 생성
* DocumentBuilderFactory -> DocumentBuilder -> Document
*/
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//여러가지 옵션들. 세팅한 값은 default value.
// dbf.setCoalescing(false);
// dbf.setExpandEntityReferences(false);
// dbf.setIgnoringComments(false);
// dbf.setIgnoringElementContentWhitespace(false);
// dbf.setNamespaceAware(false);
// dbf.setValidating(true);
DocumentBuilder db = dbf.newDocumentBuilder();
//feature 사용 예
// DOMImplementation di = db.getDOMImplementation();
// di.hasFeature("StyleSheets", "2.0");
Document doc = db.parse("a.xml");
viewDoc(doc.getDocumentElement());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//읽기 : root 노드 - getDocumentElement()
public static void readRoot(Document doc) {
//노드와 Text 출력.
Element root = doc.getDocumentElement();
Node firstChild = root.getFirstChild();
System.out.println("!root node : " + root.getNodeName() +"="+ root.getNodeValue());
System.out.println("!text of root: " + firstChild.getNodeName() +"="+ firstChild.getNodeValue());
//Root 노드의 자식 노드 개수(0부터 시작)
NodeList children = root.getChildNodes();
System.out.println("!children nodes : " + children.getLength());
}
//읽기 : 특정이름 노드 출력 - getElementsByTagName()
public static void viewNode(Element root, String nodeName) {
//getElementByTagName은 전체 XML에서 status 노드들을 찾아준다
NodeList nodes = root.getElementsByTagName(nodeName);
for (int i = 0; i < nodes.getLength(); i++)
{
Node node = nodes.item(i);
Node child = nodes.item(i).getFirstChild();
System.out.println("node name : " + node.getNodeName() + "=" +node.getNodeValue());
System.out.println("node text : " + child.getNodeName() + "=" +child.getNodeValue());
}
}
//읽기 : 전체 Node, Attribute 출력 - getNextSibling(), getAttributes()
public static void viewDoc(Node start) {
//Node 출력
System.out.println("Node : " + start.getNodeName() + "=" +
((null!=start.getNodeValue()) ? start.getNodeValue().trim() : ""));
//Attribute 출력
if (start.getNodeType() == start.ELEMENT_NODE) {
NamedNodeMap attrs = start.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Node attr = attrs.item(i);
System.out.println(" Attribute : " + attr.getNodeName() + "=" + attr.getNodeValue());
}
}
//하위 Node 출력
for (Node child = start.getFirstChild(); child != null; child = child.getNextSibling()) {
viewDoc(child);
}
}
//수정 : Node 값 변경 - setNodeValue()
public static void changeNode(Node node, String nodeValue) {
node.setNodeValue(nodeValue);
}
//수정 : Node추가(insertBefor()), attibute 추가/삭제(setAttribute/removeAttribute)
public static void addNode(Document doc) {
//추가할 노드 준비
Node addNode = doc.createTextNode("addNodeValue");
Element addElement = doc.createElement("addNodeName");
addElement.appendChild(addNode);
//attribute 추가
addElement.setAttribute("attr1", "val1");
addElement.setAttribute("attr2", "val2");
//attribute 삭제
addElement.removeAttribute("attr2");
//order라는 노드 앞에 추가
Element root = doc.getDocumentElement();
root.insertBefore(addElement, root.getElementsByTagName("order").item(0));
}
//삭제 : 노드 삭제 - removeChild()
public static void removeNode(Document doc) {
Element root = doc.getDocumentElement();
Node deleteNode = root.getElementsByTagName("customerid").item(0);
deleteNode.getParentNode().removeChild(deleteNode);
}
//대체 : 노드 대체 - replaceChild()
public static void replaceChild(Document doc) {
Element root = doc.getDocumentElement();
//대체시킬 노드 생성
Node addNode = doc.createTextNode("addNodeValue");
Element addElement = doc.createElement("addNodeName");
addElement.appendChild(addNode);
// 기존 item 노드를 customerid 위치로 넣을려면..
// Element addElement = (Element)root.getElementsByTagName("item").item(0);
//cutomerid를 빼고 그 자리에 addNodename를 넣음
Node deleteNode = root.getElementsByTagName("customerid").item(0);
deleteNode.getParentNode().replaceChild(addElement, deleteNode);
}
//파일로 저장 Transformer
public static void saveXML(Document doc) {
try {
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new FileOutputStream("b.xml"));
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer trans = transFactory.newTransformer();
trans.transform(source, result);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
}
DOM 샘플 : DOM.java
SAX 사용
"Understanding SAX :
http://www.ibm.com/developerworks/edu/x-dw-xusax-i.html " 을 보면서 따라한 샘플입니다.
소스 파일이 2개 있는데 SAX.java와 필터를 사용한 SAX_Filter.java입니다.
SAX.java는 기초적인 사용 예제로 DefaultHandler라는 여러 핸들러를 implement한 껍데기 클래스입니다.
Content나 Error등의 각기 인터페이스 클래스가 제공되므로 따로 구현해도 됩니다.
SAX 샘플 : SAX.java SAX 샘플 : SAX.java
SAX.java
package compress;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import com.sun.org.apache.xml.internal.serializer.Serializer;
import com.sun.org.apache.xml.internal.serializer.SerializerFactory;
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;
public class SAX {
public static void main(String[] args) {
/*
* SAX 드라이버를 직접 지정하는 방법
* 1. 클래스를 직접 생성
* XMLReader xmlReader = new com.sun.org.apache.xerces.internal.jaxp.SAXDriverImpl();
* 2. property 지정하면 XMLReaderFactory.createXMLReader에서 perperty를 체크한다.
* java -Dorg.xml.sax.driver=org.a.b.c.SAXDriver 프로그램
* XMLReader xmlReader = XMLReaderFactory.createXMLReader();
*
* 3. 직접 지정
* XMLReaderFactory.createXMLReader("org.a.b.c.SAXDriver());
*/
try {
//SAX 생성
//SAXParserFactory는 jre.home/lib/jaxp.properties 를 통해 지정할 수 있다.
// ex)javax.xml.parsers.SAXParserFactory=
com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
SAXParserFactory spfactory = SAXParserFactory.newInstance();
// spfactory.setValidating(false);
// spfactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
SAXParser saxParser = spfactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
ContentHandler tSaxHandler = null;
if (false) { //XML 파일로 저장하는 경우
Properties xmlProps = OutputPropertiesFactory.getDefaultMethodProperties("xml");
Serializer serializer = SerializerFactory.getSerializer(xmlProps);
try {
serializer.setOutputStream(new FileOutputStream("sax.xml"));
tSaxHandler = serializer.asContentHandler();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else { //읽을 경우
tSaxHandler = new TestSAXHandler();
}
//Handler 지정
xmlReader .setContentHandler (tSaxHandler);
xmlReader .setErrorHandler (new TestSAXHandler());
System.out.println("읽기");
//XML 읽기
try {
InputSource source = new InputSource("a.xml");
xmlReader.parse(source);
} catch (IOException e) {
e.printStackTrace();
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
class TestSAXHandler extends DefaultHandler {
//실행순서1. 처음 시작시 실행되는 메소드
public void startDocument () {
System.out.println("startDocument()");
}
//실행순서2. <?Test factor="888" ?> 를 읽어옴
public void processingInstruction (String target, String data)
throws SAXException {
System.out.println("processingInstruction : " + target +":"+ data);
}
//실행순서3. Node마다 수행되며 Node명과 attribute
public void startElement (String uri, String localName, String qName,
Attributes attributes) throws SAXException {
System.out.println("startElement : " + uri);
System.out.println("Node : " + qName);
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.getQName(i);
System.out.println(" Attribute : " + attrName +"="+ attributes.getValue(i));
}
}
//실행순서4. Node마다 수행되며 값을 가져옴. 첫번째 인자 ch[]는 XML 전체 내용임
public void characters (char[] ch, int start, int length)
throws SAXException {
String value = new String(ch, start, length).trim();
System.out.println(" value : " + value);
}
//실행순서5. Node 끝날때 실행
public void endElement (String uri, String localName, String qName)
throws SAXException {
System.out.println("endElement : " + qName);
}
//실행순서6. 마지막에 실행
public void endDocument () throws SAXException {
System.out.println("endDocument()");
}
//에러처리
@Override
public void error (SAXParseException e) throws SAXException {
System.out.println("error" + e.getMessage());
}
public void warning (SAXParseException e) throws SAXException {
System.out.println("warning" + e.getMessage());
}
public void fatalError (SAXParseException e) throws SAXException {
System.out.println("fatalError" + e.getMessage());
}
}
SAX 샘플 : SAX.java
SAX_XMLFilter.java는 필터 기능을 넣는 방법으로 각 event 전 후에 해당 메소드들이 실행되며
XMLFilterImpl 클래스를 상속하여 구현합니다.
SAX Filter 사용 샘플 : SAX_XMLFilter.java SAX Filter 사용 샘플 : SAX_XMLFilter.java
SAX_XMLFilter.java
package compress;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLFilterImpl;
import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;
import com.sun.org.apache.xml.internal.serializer.Serializer;
import com.sun.org.apache.xml.internal.serializer.SerializerFactory;
public class SAX_XMLFilter {
public static void main(String[] args) {
try {
SAXParserFactory spfactory = SAXParserFactory.newInstance();
spfactory.setValidating(false);
SAXParser saxParser = spfactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
XMLFilter xmlFilter = null;
if (true) { //파일로 저장하는 경우(xslt 사용)
TransformerFactory tFactory = TransformerFactory.newInstance();
SAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
try {
//xslt xmlFilter = saxTFactory.newXMLFilter(new StreamSource("a.xsl"));
Properties xmlProps = OutputPropertiesFactory.getDefaultMethodProperties("xml");
Serializer serializer = SerializerFactory.getSerializer(xmlProps);
serializer.setOutputStream(new FileOutputStream("sax_xmlfilter.xml"));
// serializer.setOutputStream(System.out);
xmlFilter.setContentHandler (serializer.asContentHandler());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
}
else { //파일 읽기
xmlFilter = new TestXmlFilter();
xmlFilter.setParent (xmlReader);
xmlFilter.setContentHandler (new TestSAXHandler());
xmlFilter.setErrorHandler (new TestSAXHandler());
}
//XML 읽기
try {
InputSource source = new InputSource("a.xml");
xmlFilter.parse(source);
} catch (IOException e) {
e.printStackTrace();
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
System.out.println("done");
}
}
class TestXmlFilter extends XMLFilterImpl {
public void startDocument () {
System.out.println("startDocument()");
}
public void startElement (String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println("!!!!!!!!!!");
super.startElement( uri, localName, qName, atts);
}
}
SAX Filter 사용 샘플 : SAX_XMLFilter.java
JDOM
일단, JDOM 홈페이지(
http://www.jdom.org/ ) 에서 jdom.jar 를 받아야 합니다.
"Simplify XML programming with JDOM :
http://www.ibm.com/developerworks/java/library/j-jdom/ " 와 jdom 다운시 들어있는 샘플을 보고 돌려봤습니다.
JDOM 사용 샘플 : JDOM.java JDOM 사용 샘플 : JDOM.java
JDOM.java
package compress;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.jdom.Attribute;
import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.filter.ElementFilter;
import org.jdom.input.SAXBuilder;
import org.jdom.output.DOMOutputter;
import org.jdom.output.Format;
import org.jdom.output.SAXOutputter;
import org.jdom.output.XMLOutputter;
public class JDOM {
public static void main(String[] args) {
try {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build("a.xml");
readDescendant(doc);
readElementRecursively(doc.getRootElement());
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//SAX,DOM
public static void transfer(Document doc) {
try {
//DOM의 Document로 변환 하는 방법
DOMOutputter domOutputter = new DOMOutputter();
org.w3c.dom.Document domDoc= domOutputter.output(doc) ;
//SAX처럼 이벤트 기반으로 사용 하는 방법
SAXOutputter saxOutputter = new SAXOutputter();
// saxOutputter.setContentHandler (핸들러);
// saxOutputter.setErrorHandler (핸들러));
saxOutputter.output (doc);
} catch (JDOMException e) {
e.printStackTrace();
}
}
//Document.getDescendants() 로 출력
public static void readDescendant(Document doc) {
//전체 읽기
System.out.println("All content:");
Iterator itr = doc.getDescendants();
while (itr.hasNext()) {
Content c = (Content) itr.next();
System.out.println(c);
}
//Node 정보만 읽기
System.out.println();
System.out.println("Only elements:");
itr = doc.getDescendants(new ElementFilter());
while (itr.hasNext()) {
Content c = (Content) itr.next();
System.out.println(c);
}
//Node 정보 외에 모두 읽기
System.out.println();
System.out.println("Everything that's not an element:");
itr = doc.getDescendants(new ElementFilter().negate());
while (itr.hasNext()) {
Content c = (Content) itr.next();
System.out.println(c);
}
//item 노드만 읽기
System.out.println();
System.out.println("Only elements with localname of item:");
itr = doc.getDescendants(new ElementFilter("item"));
while (itr.hasNext()) {
Content c = (Content) itr.next();
System.out.println(c);
}
//item, qty 노드만 읽기
System.out.println();
System.out.println(
"Only elements with localname of item or qty");
itr = doc.getDescendants(new ElementFilter("item").or(new ElementFilter("qty")));
while (itr.hasNext()) {
Content c = (Content) itr.next();
System.out.println(c);
}
//qty 노드 제거
System.out.println();
System.out.println("Remove elements with localname of qty:");
itr = doc.getDescendants(new ElementFilter("qty"));
while (itr.hasNext()) {
itr.next();
itr.remove();
}
//출력
try {
XMLOutputter outp = new XMLOutputter();
outp.output(doc, System.out);
} catch (IOException e) {
e.printStackTrace();
}
}
//Element, Attribute 출력
public static void readElementRecursively(Element el) {
//Node 정보 읽기
System.out.println("Node : "+ el.getName() +"="+ el.getTextTrim());
//Attribute 읽기
List attrs = el.getAttributes();
if ( null != attrs ) {
for (int i = 0; i < attrs.size(); i++) {
Attribute attr = (Attribute) attrs.get(i);
System.out.println(" "+ attr.getName() +"="+ attr.getValue());
}
}
//하위 Node 읽기
List li = el.getChildren();
if ( null != li ) {
for (int i = 0; i < li.size(); i++) {
readElementRecursively((Element)li.get(i));
}
}
}
}
JDOM 사용 샘플 : JDOM.java
StAX
StAX의 경우 API와 RI(구현체)가 여러가지 있습니다. (처음에 BEA에서 만들었군요)
http://stax.codehaus.org/ 와
http://woodstox.codehaus.org/ 에서 API와 RI의 .jar 를 받을 수 있는데
아래 샘플에선 stax.codehaus.org에서 받은 라이브러리를 사용했습니다.
다른 분들은 woodstox를 사용하시는 것 같습니다.
샘플에서 XML 파일을 읽고 쓰는데 2가지 방식(XMLStreamReader와 XMLEventWriter) 이 있습니다.
참고자료의 "StAX'ing up XML, Part1,2,3" 을 보고 만들었습니다.
StAX 사용 샘플 : StAX.java StAX 사용 샘플 : StAX.java
StAX.java
package compress;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class StAX {
public static void main(String[] args) {
String xmlFile = "a.xml";
// useXMLStreamReader(xmlFile); //XMLStreamReader로 XML 읽기
// useXMLStreamWriter(); //XMLStreamWriter로 XML 쓰기
// useXMLEventReader(xmlFile); //XMLEventReader로 XML 읽기
// useXMLEventWriter(); //XMLEventWriter로 xML 쓰기
}
//XMLEventWriter를 사용한 XML 파일 쓰기
private static void useXMLEventWriter() {
final String XHTML_NS = "http://www.w3.org/1999/xhtml";
final QName HTML_TAG = new QName(XHTML_NS, "html");
final QName HEAD_TAG = new QName(XHTML_NS, "head");
final QName TITLE_TAG = new QName(XHTML_NS, "title");
final QName BODY_TAG = new QName(XHTML_NS, "body");
XMLOutputFactory f = XMLOutputFactory.newInstance();
XMLEventWriter w = null;
try {
w = f.createXMLEventWriter(System.out);
XMLEventFactory ef = XMLEventFactory.newInstance();
w.add(ef.createStartDocument());
w.add(ef.createIgnorableSpace("\n"));
w.add(ef.createDTD("<!DOCTYPE html " +
"PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " +
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"));
w.add(ef.createIgnorableSpace("\n"));
w.add(ef.createStartElement(HTML_TAG, null, null));
w.add(ef.createNamespace(XHTML_NS));
w.add(ef.createAttribute("lang", "en"));
w.add(ef.createIgnorableSpace("\n"));
w.add(ef.createStartElement(HEAD_TAG, null, null));
w.add(ef.createStartElement(TITLE_TAG, null, null));
w.add(ef.createCharacters("Test"));
w.add(ef.createEndElement(TITLE_TAG, null));
w.add(ef.createEndElement(HEAD_TAG, null));
w.add(ef.createIgnorableSpace("\n"));
w.add(ef.createStartElement(BODY_TAG, null, null));
w.add(ef.createCharacters("This is a test."));
w.add(ef.createEndElement(BODY_TAG, null));
w.add(ef.createEndElement(HTML_TAG, null));
w.add(ef.createEndDocument());
System.out.println("--");
} catch (XMLStreamException e) {
e.printStackTrace();
} finally {
try {
if (null != w) w.close(); //write
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
}
//XMLStreamWriter 사용한 XML 파일 쓰기
private static void useXMLStreamWriter() {
final String XHTML_NS = "http://www.w3.org/1999/xhtml";
XMLOutputFactory f = XMLOutputFactory.newInstance();
XMLStreamWriter w = null;
try {
w = f.createXMLStreamWriter(System.out);
w.writeStartDocument();
w.writeCharacters("\n");
w.writeDTD("<!DOCTYPE html " +
"PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " +
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
w.writeCharacters("\n");
w.writeStartElement(XHTML_NS, "html");
w.writeDefaultNamespace(XHTML_NS);
w.writeAttribute("lang", "en");
w.writeCharacters("\n");
w.writeStartElement(XHTML_NS, "head");
w.writeStartElement(XHTML_NS, "title");
w.writeCharacters("Test");
w.writeEndElement();
w.writeEndElement();
w.writeCharacters("\n");
w.writeStartElement(XHTML_NS, "body");
w.writeCharacters("This is a test.");
w.writeEndElement();
w.writeEndElement();
w.writeEndDocument();
} catch (XMLStreamException e) {
e.printStackTrace();
} finally {
try {
if (null != w) w.close(); //write
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
}
//XMLStreamReader 사용한 XML 읽기
public static void useXMLStreamReader(String xmlFile) {
InputStream input = null;
XMLStreamReader r = null;
try {
//StAX생성
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
input = new FileInputStream(xmlFile);
r = factory.createXMLStreamReader(input);
//READ
while ( r.hasNext() ) {
int elType = r.next();
switch (elType) {
case XMLStreamConstants.START_DOCUMENT:
System.out.println("!!starat document");
break;
case XMLStreamConstants.START_ELEMENT:
System.out.println("-- Start Element: " + r.getName());
for(int i = 0, n = r.getAttributeCount(); i < n; ++i) {
QName name = r.getAttributeName(i);
String value = r.getAttributeValue(i);
System.out.println(" Attribute: " + name + "=" + value);
}
break;
case XMLStreamConstants.CHARACTERS:
if (r.isWhiteSpace())
break;
System.out.println(" characters: " + r.getText());
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("-- nd element");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("!!end document");
break;
default:
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
} finally {
try {
if (null != r) r.close();
if (null != input) input.close();
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//XMLEventReader 사용한 XML 읽기
public static void useXMLEventReader(String xmlFile) {
InputStream input = null;
XMLEventReader r = null;
try {
//StAX생성
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
//XMLEventReader 사용
input = new FileInputStream(xmlFile);
r = factory.createXMLEventReader(input);
//READ
while ( r.hasNext() ) {
XMLEvent event = r.nextEvent();
//XMLStreamReader 때처럼 type으로
switch (event.getEventType()) {
case XMLStreamConstants.START_DOCUMENT:
System.out.println("!!starat document");
break;
case XMLStreamConstants.START_ELEMENT:
StartElement start = event.asStartElement();
System.out.println("-- Start Element: " + start.getName().getLocalPart());
//Attribute 출력
Iterator it = start.getAttributes();
while ( it.hasNext() ) {
Attribute attr = (Attribute) it.next();
System.out.println(" Attribute: " + attr.getName().getLocalPart()+"="+ attr.getValue());
}
break;
case XMLStreamConstants.CHARACTERS:
Characters characters = event.asCharacters();
System.out.println(" characters: " + characters.getData().trim());
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("-- nd element");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("!!end document");
break;
default:
break;
}
//if 문으로 잡기
if ( event.isStartDocument() ) {
System.out.println(">>>> isSTartDocument() ");
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
} finally {
try {
if (null != r) r.close();
if (null != input) input.close();
} catch (XMLStreamException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
StAX 사용 샘플 : StAX.java
참고자료 : (IBM developerworks의 경우 일부 글들은 가입하셔야 볼 수 있습니다.)