1. xml 태그와 XPath
xml 태그를 사용하기 위해서는 XPath 를 먼저 이해할 필요가 있다. xml 소스 트리의 정확한 위치를 지정해주기 위한 경로지정 문법이며 XSLT와 XPointer 를 위해서 만들어진 것이다. xml 엘리먼트들을 노드(node) 로 접근한다. 파일 시스템과 유사하며 다음과 같은 특성이 있다.
/ 로 시작하면 절대경로처럼 root node 에서 시작된다.
//로 시작할 경우는 모든 영역에서 해당 엘리먼트를 선택하게 된다. * 표시는 이전 엘리먼트 아래의 모든 자식 엘리먼트를 나타낸다.
동일한 엘리먼트들이 있을 경우, [] 안에 포함된 숫자는 엘리먼트의 순번이다. 조건식이 올 경우 해당하는 것이 선택된다. last() 일 경우는 맨 마지막 엘리먼트를 표시한다. 속성은 @ 로 시작된다. normalize-space() 함수는 앞뒤 공백을 제거하는 trim() 역할을 한다.
이 장에 나오는 XPath의 기능은 이 정도로 소개하겠고, XPath에 관한 보다 자세한 내용은 이 장의 마지막에 소개한 인터넷 튜토리얼을 참고하기 바란다.
JSTL에서 XPath를 통해서 내장객체에 쉽게 접근할 수 있다.
표현 |
매핑 |
$foo |
pageContext.findAttribute("foo") |
$param:foo |
request.getParameter("foo") |
$header:foo |
request.getHeader("foo") |
$cookie:foo |
maps to the cookie's value for name foo |
$initParam:foo |
application.getInitParameter("foo") |
$pageScope:foo |
pageContext.getAttribute( "foo", PageContext.PAGE_SCOPE) |
$requestScope:foo |
pageContext.getAttribute( "foo", PageContext.REQUEST_SCOPE) |
$sessionScope:foo |
pageContext.getAttribute( "foo", PageContext.SESSION_SCOPE) |
$applicationScope:foo |
pageContext.getAttribute( "foo", PageContext.APPLICATION_SCOPE) |
예를 들어서 다음 문장은 parameter 로 받은 "name"의 값이 bar엘리먼트의 x속성의 값과 같은 것들을 선택하게 된다.
/foo/bar[@x=$param:name]
xml 태그는 다음과 같은 것들이 있다.
기능 |
태그 |
prefix |
기본 |
out, parse, set |
x |
흐름 제어 |
choose (when, otherwise), forEach, if |
|
변환 |
transform (param) |
xml 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x"%>
2. <x:out/>
XPath에 지정한 패턴에 따라 xml내용을 출력하는 <x:out/> 태그의 형식은 다음과 같다.
Syntax <x:out select="XPathExpression" [escapeXml="{true|false}"]/>
|
3. <x:parse/>
xml문서를 읽어서 파싱하는 <x:parse/> 태그는 다음과 같은 형식이다.
Syntax 1: String 또는 Reader 객체로 지정된 XML 문서 <x:parse xml="XMLDocument" {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]} [systemId="systemId"] [filter="filter"]/>
Syntax 2: body 내용으로 지정된 XML 문서 <x:parse {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]} [systemId="systemId"] [filter="filter"]> 파싱할 XML 문서 </x:parse> scopeName 은 {page|request|session|application} 중의 하나
|
4. <x:set/>
XPath에 따라 선택된 내용을 변수에 저장하는 <x:set/> 태그의 형식은 다음과 같다.
Syntax <x:set select="XPathExpression" var="varName" [scope="{page|request|session|application}"]/> |
5. <x:if/>
<c:if/> 태그와 마찬가지로 xml태그에도 <x:if/> 가 있고 형식은 <c:if/> 태그와 유사하다. <x:if/>의 형식은 다음과 같다.
Syntax 1: Body 없는 경우 <x:if select="XPathExpression" var="varName" [scope="{page|request|session|application}"]/>
Syntax 2: Body 있는 경우 <x:if select="XPathExpression" [var="varName"] [scope="{page|request|session|application}"]> body content </x:if> |
test 속성 대신에 select 속성으로 진위를 따지는데, 다음 3가지 기준을 유념할 필요가 있다. 이 세 가지 기준은 <x:choose/>의 <x:when/> 과 <x:forEach/> 에서도 동일하게 사용된다.
1. number 가 true 인 때는 + 또는 – 0 도 아니고, NaN(Not A Number) 도 아닐 경우 2. node-set 이 true 인 때는 empty 가 아닐 경우 3. string 이 true 인 때는 길이가 0 이 아닐 경우 |
6. <x:choose/>, <x:when/>, <x:otherwise/>
<c:choose/> 태그와 마찬가지로 xml태그에도 <x:choose/> 가 있고 형식은 <c:choose/> 태그와 유사하다.
Syntax <x:choose> body content (<x:when> and <x:otherwise> 서브태그) </x:choose>
Syntax <x:when select="XPathExpression"> body content </x:when>
Syntax <x:otherwise> conditional block </x:otherwise> |
7. <x:forEach/>
<x:forEach/> 태그는 XPath에 따라서 해당하는 엘리먼트 수만큼 반복하게 된다.
Syntax <x:forEach [var="varName"] select="XPathExpression"> body content </x:forEach>
|
xml 태그를 활용한 예제이다.
예제 20. jstlxml01.jsp |
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %> <% response.setContentType("text/html;"); %> <%-- 파라메터 받아서 출력 --%> <c:if test="${!empty param.name}"> param: <x:out select="$param:name"/> </c:if> <form> name: <input type="text" name="name"> <input type="submit"> </form> <hr> <%-- xml 데이터를 xdata 변수에 할당 --%> <x:parse var="xdata"> <namecard> <person> <name>허광남</name> <id>남자</id> <email>kenu@email.com</email> <phone>111-2222-3333</phone> </person> <person> <name>노재춘</name> <id>남자</id> <email>suribada@email.com</email> <phone>222-3333-4444</phone> </person> <person> <name>이선재</name> <id>남자</id> <email>hsboy@email.com</email> <phone>333-4444-5555</phone> </person> </namecard> </x:parse> <%-- XPath 를 이용해서 xdata에서 추출 --%> <x:out select="$xdata//person[1]/name"/> <x:out select="$xdata//person[last()]/name"/> <hr> <%-- person 으로 반복해서 email과 phone 출력 --%> <table border="1"> <x:forEach select="$xdata//person"> <tr><td><x:out select="email" /></td> <td><x:out select="phone" /></td></tr> </x:forEach> </table>
|
파라메터 name 의 접근은 EL에서는 ${param.name} 으로 사용하지만 XPath 에서는 $param:name 을 사용한다는 차이가 있다.
파라메터를 받아서 <x:out/> 으로 출력하는 부분이 제일 상단이고, 그 다음은 xml 데이터를 파싱하는 부분이다.
DTD 까지 쓰지 않아도 형식이 잘 갖춰지기만 하면 (well-formed) xml 데이터로 인식을 한다. 이것을 xdata라는 변수에 할당한 다음에 이후에 처리하게 된다.
xml 데이터는 파일로 따로 만든 후에 접근할 수 있다. 이때는 <c:import> 를 같이 사용하는데, 다음과 같이 쓸 수 있다.
예제 21. namecard.xml |
<?xml version="1.0" encoding="euc-kr" ?> <namecard> <person> <name>허광남</name> <id>남자</id> <email>kenu@email.com</email> <phone>111-2222-3333</phone> </person> <person> <name>노재춘</name> <id>남자</id> <email>suribada@email.com</email> <phone>222-3333-4444</phone> </person> <person> <name>이선재</name> <id>남자</id> <email>hsboy@email.com</email> <phone>333-4444-5555</phone> </person> </namecard>
|
예제 22. jstlxml02.jsp |
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x"%> <% response.setContentType("text/html;"); %> <%-- namecard.xml 파일을 불러와 xdata 변수에 할당 --%> <c:import url="namecard.xml" var="xmldata" /> <x:parse xml="${xmldata}" var="xdata"/>
<%-- XPath 를 이용해서 xdata에서 추출 --%> <x:out select="$xdata//person[1]/name"/> … 이하 생략 …
|
이 xdata 변수에 들어간 xml 에서 추출하는 방식은 XPath 를 사용한다고 했다.
$select="$xdata//person[1]/name" 에서 person[1] 은 person 으로 사용하는 것과 같다. [] 안에는 순서가 들어가고 생략될 경우 첫 엘리먼트를 찾기 때문이다.
<x:forEache/> 태그로 <person> 엘리먼트 수만큼 반복하게 했다. 이때 자동으로 기준은 <person> 이 되기 때문에 그 이후에 <email> 이나 <phone> 엘리먼트들은 /person/email 과 /person/phone 을 바로 참조하게 된다.
8. <x:transform/>, <x:param/>
xml과 xslt 파일을 결합해서 새로운 형식의 문서를 생성해 내는 <x:transform/>의 형식은 다음과 같다.
Syntax 1: Body 없는 경우 <x:transform xml="XMLDocument" xslt="XSLTStylesheet" [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"] [{var="varName" [scope="scopeName"]|result="resultObject"}]>
Syntax 2: 변환 파라메터를 body에서 지정하는 경우 <x:transform xml="XMLDocument" xslt="XSLTStylesheet" [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"] [{var="varName" [scope="scopeName"]|result="resultObject"}]> <x:param> 액션들 </x:transform>
Syntax 3: XML문서와 선택적 변환 파라메터들이 body에 지정된 경우 <x:transform xslt="XSLTStylesheet" xmlSystemId="XMLSystemId" xsltSystemId="XSLTSystemId" [{var="varName" [scope="scopeName"]|result="resultObject"}]> XML Document optional <x:param> actions </x:parse> scopeName 은 {page|request|session|application} 중에 하나
|
var 속성에 지정된 결과와 result 속성에 지정된 결과의 차이점은 var 속성은 scope 지정해서 다른 곳에서도 사용할 수 있고, result 는 현재 페이지에서만 사용할 수 있다는 것이다.
또한 타입도 차이가 나는데, var는 org.w3c.dom.Document 로, result는 javax.xml.transform.Result 객체로 저장이 된다.
xml의 파라메터를 지정하는 <x:param/> 태그의 형식은 다음과 같다.
Syntax Syntax 1: value 속성에 파라메터 값이 지정된 경우 <x:param name="name" value="value"/>
Syntax 2: body 내용에 파라메터 값이 지정된 경우 <x:param name="name"> parameter value </x:param>
|
여기서 잠깐 |
<x:transform/> 태그를 사용할 때 jdk1.4 내에 있는 xalan과 jstl이 충돌을 일으킨다. 이런 경우, 톰캣 실행을 중지하고, jstl의 WEB-INF/lib디렉토리에 있는 xalan.jar 파일과 xercesImpl.jar 파일 두 개를 <CATALINA_HOME>/common/endorsed 디렉토리에 복사한다. 이전 버전의 xercesImpl.jar 파일을 덮어씌운다. 만일 이 과정이 생략되면, 다음과 같은 예외를 만나게 된다. org.apache.xml.utils.WrappedRuntimeException:
The output format must have a '{http://xml.apache.org/xslt}content-handler' property! |
<x:transform/> 활용 예제를 보자.
예제 23. jstlxml03.jsp |
<%@ page pageEncoding="MS949" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html> <head> <title>JSTL: XML Support -- Transform</title> </head> <body bgcolor="#FFFFFF"> <c:set var="xml"> <?xml version="1.0" encoding="MS949"?> <namecard> <person> <name>허광남</name> <id>남자</id> <email>kenu@email.com</email> <phone>111-2222-3333</phone> </person> <person> <name>노재춘</name> <id>남자</id> <email>suribada@email.com</email> <phone>222-3333-4444</phone> </person> <person> <name>이선재</name> <id>남자</id> <email>hsboy@email.com</email> <phone>333-4444-5555</phone> </person> </namecard> </c:set>
<c:set var="xsl"> <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <table border="1"> <tr> <th>이름 </th> <th>이메일</th> <th>연락처</th> </tr> <xsl:for-each select="namecard/person"> <tr> <td><xsl:value-of select="name" /></td> <td><xsl:value-of select="email" /></td> <td><xsl:value-of select="phone" /></td> </tr> </xsl:for-each> </table> </xsl:template>
</xsl:stylesheet> </c:set>
<x:transform xml="${xml}" xslt="${xsl}"/>
</body> </html>
|
jsp 소스 안에 있는 xml(예제 21. namecard.xml) 과 xsl을 따로 파일로 빼놓으면 아래와 같이 바뀐다.
예제 24. namecard.xsl |
<?xml version="1.0" encoding="euc-kr" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <table border="1"> <tr> <th>이름 </th> <th>이메일</th> <th>연락처</th> </tr> <xsl:for-each select="namecard/person"> <tr> <td><xsl:value-of select="name" /></td> <td><xsl:value-of select="email" /></td> <td><xsl:value-of select="phone" /></td> </tr> </xsl:for-each> </table> </xsl:template>
</xsl:stylesheet>
|
xsl 에 관한 문법적인 내용은 여기에서 다루지 않겠다.
namecard.xsl 파일은 namecard.xml 에 html 을 입히는 역할을 하게 되며, 데이터를 제외한 html 틀을 갖고 있다고 볼 수 있다.
이 두 개의 파일을 하나로 합쳐서 html 코드를 만들어 내는 소스는 다음과 같다.
예제 25. jstlxml04.jsp |
<%@ page pageEncoding="MS949" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<html> <head> <title>JSTL: XML Support -- Transform</title> </head> <body bgcolor="#FFFFFF"> <h1>연락처</h1> <c:import var="xml" url="namecard.xml" charEncoding="MS949"/> <c:import var="xsl" url="namecard.xsl" charEncoding="MS949"/>
<x:transform xml="${xml}" xslt="${xsl}"/>
</body> </html>
|
jstlxml03.jsp 에서 <x:set/> 부분은 <c:import/> 로 바뀌었고, 파일을 불러올 때 charEncoding 속성을 통해서 인코딩해 주었다.
xml 변수와 xsl 변수 두 개를 파싱하지 않고 바로 <x:transform/> 을 통해서, jsp 파일에 출력했다.
<x:transform/> 에 var 속성을 주면 출력되지 않고, 변수에 org.w3c.dom.Document 타입으로 저장된다.
이렇게 JSTL 의 4가지 표준 태그에 대해서 알아보았다. 프로그래밍의 기본인 조건, 반복, 연산이 가능하기 때문에 스크립틀릿을 거의 모두 제거할 수 있음을 알 수 있었다.
'강의노트 > 웹' 카테고리의 다른 글
DB연결하기 (0) | 2013.07.17 |
---|---|
CSS (0) | 2013.07.15 |
JSTL SQL 태그 (0) | 2013.07.11 |
JSTL 국제화 지역화 태그 (0) | 2013.07.10 |
JSTL core (0) | 2013.07.10 |