[JAXB] Unmarshal 시 dtd 를 명확하게 정의하여 처리하기
JAVA/JAXB / 2011. 1. 21. 01:30
<!DOCTYPE pubdoc SYSTEM "pubdoc.dtd">
위와 같이 XML 에 dtd 가 정의되어 있는 경우 JAXB 로 unmarshal 을 할 경우 dtd 의 위치가 명확하지 않아 재대로 unmarshal 이 되지 않을 수 있습니다.
좀 더 안전한 시스템을 위해서는 명확하게 정의해야 하는데요... 아래와 같은 방법을 사용합니다.
01 | String data = "xml data..." ; |
02 | Pubdoc pubdoc = null ; |
03 | try { |
04 | XMLReader xmlReader = XMLReaderFactory.createXMLReader(); |
05 | EntityResolver entityResolver = new EntityResolver() { |
06 | public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { |
07 | String resourceName = "pack.dtd" ; |
08 | if (systemId != null ) { |
09 | resourceName = systemId.substring(systemId.lastIndexOf( "/" ) + 1 ); |
10 | } |
11 | return new InputSource(PubdocParser. class .getResourceAsStream( "/dtd/" + resourceName)); |
12 | } |
13 | }; |
14 | xmlReader.setEntityResolver(entityResolver); |
15 | SAXSource saxSource = new SAXSource(xmlReader, new InputSource( new StringReader(data))); |
16 | pack = (Pack) unmarshaller.get().unmarshal(saxSource); |
17 | } catch (JAXBException e) { |
18 | e.printStackTrace(); |
19 | } catch (SAXException e) { |
20 | e.printStackTrace(); |
21 | } finally { |
22 | |
23 | } |
XMLReader 객체에 설정된 EntityResolver 를 통해 해당 dtd 와 관련된 정보들을 InputSource 로 참조할 수 있도록 처리하는 것 입니다.
EntityResolver 의 resolveEntity 메소드는 필요로 하는 리소스들을 두번째 파라미터인 syustemId 로 넘기게 됩니다.
즉, "C:/JAVA/Temp" 폴더에서 실행을 한다면 "pubdoc.dtd" 는 "C:/JAVA/Temp/pubdoc.dtd" 에서 찾게 됩니다. 해당 systemId 를 적당히 잘라내어 클래스패스 내에 리소스의 위치와 결합시켜서 로드하는 방식을 사용하였습니다.
먼가 systemId 자르는 것이 찝찌름 하지만 정상구동 확인하였습니다.