2017. 4. 19. 07:56

[Java] XStream을 사용한 XML 파싱




XStream 라이브러리를 사용하여 XML 파싱하는 예제소스 입니다.



build.gradle 에 라이브러리 추가 (Gradle 사용 시)

// https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream

compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.9' 


Gradle 사용하지 않고 진행 시 라이브러리는 직접 다운받아서 추가해 줍니다.



main 소스

package xmlparse;


import java.net.URL;

import java.net.URLConnection;


import com.thoughtworks.xstream.XStream;

import com.thoughtworks.xstream.io.xml.DomDriver;


import xmlparse.vo.Book;

import xmlparse.vo.Catalog;


public class xmlparse {


public static void main(String[] args) throws Exception {


// XStream 인스턴스 생성

        XStream xstream = new XStream(new DomDriver());

        

        // alias 설정 XML tag, 담당할 class 지정

        // 각 클래스는 해당 태그가 가진 항목을 구성하고 있다

        xstream.alias("catalog", Catalog.class);

        xstream.alias("book", Book.class);

        xstream.addImplicitCollection(Catalog.class, "books");

        

        // 태그의 어노테이션 처리 

        // <book id="xxx"> 에서 xxx 를 읽어오기 위해 필요하다

        // [REF] http://stackoverflow.com/questions/18106619/xstreamasattribute-not-adding-as-attribute-xstream

        //xstream.autodetectAnnotations(true);  // auto 속성을 지정하게 되면 모두 처리하는 듯 하다. (귀찮으면 걍 이거 쓰자 ;;)

        xstream.processAnnotations(Book.class); // 각 속성별로 읽어오도록 지정 한다.

        

        // XML 로드

        URL url = new URL("http://haebi.net/book.xml");

        URLConnection conn = url.openConnection();

        

        // 최상위 태그로부터 XML 파싱

        Catalog var = (Catalog)xstream.fromXML(conn.getInputStream());

        

        // 반복문 돌면서 처리한다

        for(int i=0; i<var.books.size(); i++)

        {

        Book book = var.books.get(i);

        System.out.println(book.id);

        System.out.println(book.author);

        }

        

}


book.java

package xmlparse.vo;


import com.thoughtworks.xstream.annotations.XStreamAlias;

import com.thoughtworks.xstream.annotations.XStreamAsAttribute;


@XStreamAlias("book")

public class Book {

@XStreamAsAttribute

    public String id;

public String author;

public String title;

public String genre;

public String price;

public String publish_date;

public String description;

// 갯수가 멀티개인 속성을 가지면...

//@XStreamImplicit(itemFieldName="reply")

//private ArrayList<string> reply

}


catalog.java

package xmlparse.vo;


import java.util.LinkedList;

import java.util.List;


import com.thoughtworks.xstream.annotations.XStreamAlias;

import com.thoughtworks.xstream.annotations.XStreamAsAttribute;


@XStreamAlias("catalog")

public class Catalog {

public List<Book> books = new LinkedList<Book>();

}



Depth 가 낮은 XML 처리에는 유용하겠는데, 깊어지면 답이 없어 보인다. ;;;

10 depth 까지 내려가면 클래스 언제 다 맹글어 -_-;;




Posted by 해비
2017. 4. 18. 01:54

XPath를 활용한 XML 파싱



syntaxhighliter 에서 코드가 뭉개져서 그냥 붙여넣기 했더니 보기가 영 그렇다.


gist 에 올린 소스가 더 이쁘게 보여지므로 참고

[gist 링크] https://gist.github.com/haebi/29070dda0556fc6fba5909b45a067faa



소스코드

package xmlparse2;


import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.xpath.XPath;

import javax.xml.xpath.XPathConstants;

import javax.xml.xpath.XPathFactory;


import org.w3c.dom.Document;

import org.w3c.dom.NodeList;


public class XmlParse2 {


public static void main(String[] args) throws Exception {

// 샘플 XML 파일(books.xml)

// [REF] https://msdn.microsoft.com/ko-kr/library/ms762271(v=vs.85).aspx

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse("http://haebi.net/book.xml");

// XPath 인스턴스 생성

XPath xpath = XPathFactory.newInstance().newXPath();

// 대상 노드 지정

String expression = "/catalog/book";

// 지정 노드로 부터 노드목록 획득

NodeList nl = (NodeList) xpath.evaluate(expression, doc, XPathConstants.NODESET);

// 첫번째 노드의 부모 노드명을 출력

System.out.println(nl.item(0).getParentNode().getNodeName());

System.out.println("sub node start!!");

System.out.println("-----------------------------------------------------");

// 1번째  book 노드의 자식노드 목록을 획득

NodeList cnl = nl.item(0).getChildNodes(); // author, title, genre, price, publish_date, description

System.out.println(cnl.item(0).getParentNode().getNodeName());


// 확보된 노드 목록을 순서대로 출력

for(int i=0; i<cnl.getLength(); i++)

{

// 노드 이름이 #text로 출력되는 문제로 스킵 하도록 설정하였다. 

// xml파일의 들여쓰기로 인한 문제 인듯 하다.

if("#text".equals(cnl.item(i).getNodeName()))

continue;

// 현재 노드 인덱스 번호 출력

System.out.println(i);

// 노드 명 출력

System.out.println("NODE : " + cnl.item(i).getNodeName());

// 노드 값 출력

System.out.println("VALUE : " + cnl.item(i).getTextContent());

}

System.out.println("-----------------------------------------------------");

}

}



출력

Start!!

catalog

sub node start!!

-----------------------------------------------------

book

1

NODE : author

VALUE : Gambardella, Matthew

3

NODE : title

VALUE : XML Developer's Guide

5

NODE : genre

VALUE : Computer

7

NODE : price

VALUE : 44.95

9

NODE : publish_date

VALUE : 2000-10-01

11

NODE : description

VALUE : An in-depth look at creating applications 

      with XML.

----------------------------------------------------- 




Posted by 해비
2011. 4. 13. 10:52

1. exam01.java 소스코드 작성

묵시적 형 변환에 관련된 예제 입니다.


3 - short형 변수 S01 에 10을 대입합니다.
4 - short형 변수 S02 에 20을 대입합니다.
5 - short형 변수 S03 에 10+20의 결과를 대입합니다.
6 - short형 변수 S04 에 변수S01 과 변수 S02를 더한다음 그것의 결과를 대입합니다.*
7 - long형 변수 S05 에 변수S01 과 변수 S02를 더한다음 그것의 결과를 대입합니다.


저장 후, 컴파일 하면 에러가 발생합니다.

6번째 라인에서 오류가 발생했음을 알리는 메시지 입니다.


이유....
자바에서 연산을 하면서 변수 타입이 기본으로 자동 지정되어졌기 때문입니다.
정수 + 정수 에서 기본 데이터 타입이 int 형인데 이것을 int보다 작은 크기인 short 에 넣겠다고 해서 발생한 오류입니다.


[해결 방법]
방법1 - 연산 부분을 괄호로 묶고 앞에 명시적 형 변환을 합니다.
           short S04 = (short)(S01+S02)

방법2 - 변수 S04의 타입을 int 형으로 선언 합니다.
         int S04 = S01+S02

방법3 - 변수 S04의 타입을 String 형으로 선언 하고, 뒤에 +"" 를 추가하여 문자화 합니다
           (주의! - 방법3 의 경우, 데이터가 문자열로 인식됩니다.)
           String S04 = S01+S02+""



* 자바에서 연산시 기본으로 지정되는 데이터 타입
정수연산 - int
실수연산 - double
문자결합 - String

정수 + 정수 = int
정수 + 실수 = double
정수 or 실수 + "문자" = String


그냥 간단하게...
작은 크기에서 큰 크기로 형 변환은 자동(묵시적)으로 이루어 지지만, 그 반대 의 경우에는 반드시 명시적으로 형 변환을 해 주어야 합니다.

보다 자세한 데이터타입이나 크기는 검색을...
Posted by 해비
2011. 4. 5. 10:44

1. Hello.java 소스코드 작성

단 5줄 짜리의 초간단 예제 입니다.
(에디트 플러스, 메모장, 이클립스 기타... 어떤 툴을 사용하셔도 상관없습니다)



2. 컴파일
javac Hello.java

Hello.java 파일이 있는 경로로 가서 위와 같이 컴파일을 합니다.
.class 파일이 결과물로 생성됩니다.



3. 실행
java Hello

위 소스코드의 3번째 라인에 있는...
Hello World!
가 출력되면 정상적으로 컴파일 및 실행이 된 겁니다.

주의 : 실행 시, 확장자는 적으면 안됩니다.
예) java Hello.class -> 실행 안됨!!




public static void main(String[] args)
또는
public static void main(String args[])
어느쪽이든 좋습니다.

public - 접근제어를 뜻합니다. (공개 - 클래스내부, 외우 어디에서든 접근 가능)
static - 공유를 의미합니다. (모든 객체에서 공통으로 사용)
void - 리턴값이 없음을 의미 합니다.
(보다 자세한 내용은 뒤에서 다루겠습니다)

String[] args 는 실행시 매개변수를 받아오기 위한 용도로 쓰여집니다.
java Hello [매개변수1] [매개변수2] [...]


public static void main(String[] args)는 형식이 딱 지정되어있으므로 암기해 두는것이 좋습니다.
자바에서 프로그램의 시작점이 되는 곳입니다.


매개변수의 구분은 스페이스(띄움) 이며, 각 매개변수는 배열로 받아오게 됩니다.

그렇게 조금 변경된 Hello.java 의 소스코드 입니다.

args[0]
args[1]
의 2개의 매개변수를 받아와서 출력하는 구분이 추가되었습니다.

컴파일 후,
실행시 뒤에 관련 매개변수값(아무거나...) 넣어주시면 되겠습니다

위와 같이 실행이 되어집니다.

그런데,
매개변수가 모자르거나 아예 없을경우는 에러가 발생합니다.

위 코드를 보면 4번째 라인에서 오류가 발생하였음을 알리고 있습니다.

즉, 매개변수 배열의 0번째가 존재하지 않는데 0번째의 값을 가져다 쓰려고 한다고 예외가 발생했음을 알립니다.

이것마저 해결하고자 한다면은...
try~ catch 구문을 이용하여 오류 발생시 catch 블럭으로 처리를 던지는 식으로 오류 처리를 할수 있습니다만, 여기서 이것까지 하지는 않습니다.
다만, 이런 방법도 있다는 것을 알려드립니다.
(자세한 내용은 뒤에서 다루도록 하겠습니다)



[체크 사항]
Java 소스파일의 파일명은 main 메소드가 포함된 클래스의 명으로 지정하여야 한다!



Posted by 해비
2010. 8. 4. 20:53

PATH 추가
JDK의 Bin 폴더 경로
C:\Java\jdk1.6.0_21\bin

1. JAVA_HOME 지정
내 컴퓨터(우클릭) -> 속성 -> 고급 시스템설정 -> 고급 탭 선택 -> 환경변수

(윈도우7 기준... XP나 기타 운영체제에서는 약간 다를수 있습니다)

Bin 폴더 이전 까지의 JDK 경로를 설정합니다.
(각자 자신이 설치한 환경에 맞도록...)



2. PATH 설정

주의 : Path 부분을 수정할 때에는 기존의 내용이 손상되지 않도록 주의 해야 합니다!!

제일 뒤에 ; (세미콜론) 붙이고
%JAVA_HOME%\Bin 을 추가 합니다.



3. 테스트

cmd 창에서
java -version
javac -version
각각 위와 같은 메시지가 뜨면 환경설정은 완료된 것입니다.

똑같이 했는데도 안되는 경우, 기존의 cmd 창을 닫고 다시 cmd 창을 열어서 해보시기 바랍니다.
(환경설정 이전에 미리 열려진 cmd 창에서는 이전의 환경변수가 적용되어 있습니다)


Posted by 해비
2010. 7. 16. 15:48

Samples
출력결과
kkk, Java




Posted by 해비