JSTL XML 태그

강의노트/웹 2013. 7. 11. 14:35

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