14.5. XSLT
모델 데이타를 XML 형식으로 출력할 수 있습니다.
1. 컨트롤러를 만들고 등록합니다.
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
List<MemberInfo> infos = ServiceManager.getMemberInfoService().getAll();
Map<String, Object> members = new HashMap<String, Object>();
members.put("members", infos);
return new ModelAndView("memberListXml", members);
}
}
2. 모델 데이타를 XML 로 만드는 view 클레스를 만듭니다.
@SuppressWarnings("unchecked")
@Override
protected Source createXsltSource(Map model, String rootName, HttpServletRequest request, HttpServletResponse response) throws Exception {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElement(rootName);
List<MemberInfo> memberInfos = (List<MemberInfo>) model.get("members");
for (MemberInfo memberInfo : memberInfos) {
String name = memberInfo.getName();
String email = memberInfo.getEmail();
String home = memberInfo.getHome();
String pictureAddress = memberInfo.getPictureAddress();
Element memberInfoNode = document.createElement("memberInfo");
Text nameText = document.createTextNode(name);
Text emailText = document.createTextNode(email);
Text homeText = document.createTextNode(home);
Text pictureAddressText = document.createTextNode(pictureAddress);
memberInfoNode.appendChild(nameText);
memberInfoNode.appendChild(emailText);
memberInfoNode.appendChild(homeText);
memberInfoNode.appendChild(pictureAddressText);
root.appendChild(memberInfoNode);
}
return new DOMSource(root);
}
}
이때 Text, Element, Document 객체의 패키지는 org.w3c.dom 패키지 입니다. 레퍼런스의 예제는 Generic을 사용하지 않는 Map과 List 그리고 Iterator를 명시적으로 사용하고 있더군요. Java 5버전 형태로 바꿔주면 좋을텐데 말이죠. :)
변수와 메소드 이름의 작명을 잘해뒀기 때문에 직감적으로 대강 어떻게 코딩 해야 하는지 알 수 있습니다.
3. 뷰 프로퍼티 파일 정의하기.
memberListXml.stylesheetLocation=/WEB-INF/xsl/memberList.xslt
memberListXml.root=memberInfos
class 는 위에서 만든 view 클레스
stylesheetLocation은 XML을 HTML로 변환하여 보여줄 xslt 의 위치
root 는 XML의 root 엘리먼트 이름을 나타냅니다.
뷰 프로퍼티 파일을 썼다는 것은 ResourceBundleViewResolver를 사용하였다는 것입니다. 기존에 사용하던 리졸버와 상관없이 추가로 등록해 주면 됩니다. 대신 어차피 기본적으로 InternalResourceViewResolver 이 녀석이 Resolver Chaining 할 때 맨 뒤로 가긴 하지만 그래도 명시적으로 order 프로퍼티를 사용하여 순서를 명확히 해줍니다.
<!-- XML, Exel, PDF -->
<bean id="ExViewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
<property name="order" value="1" />
</bean>
<!-- jstl -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
</bean>
4. XSLT 만들기
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head><title>AJN Members</title></head>
<body>
<h1>전체 회원 목록(XML)</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="memberInfo">
<xsl:value-of select="."/><br/>
</xsl:template>
</xsl:stylesheet>
<xsl:apply-templates/> 이녀석은 xml 보여줄 곳을 명식하는 것 같고 이 부분에 뿌려줄 내용을 아랫 부분에서 정의해 주는 것 같습니다. 저기서 memberInfo 는 위의 View 클레스 만들 때 사용한 Element의 이름과 동일해야 합니다.
5. 데모