앞에서 변수를 처음 써보았다. XSLT에 변수가 있다는 것은 XSL에 T를 더하게 해준다.
변수사용에 대한 예문을 다시 가져와 보자..
<?xml version="1.0" encoding="euc-kr"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<!-- root element -->
<xsl:template match="/list">
<xsl:variable name="시작번호" select="2"/>
<xsl:variable name="끝번호" select="4"/>
<xsl:for-each select="person[position() >= $시작번호 and position() < $끝번호]">
<xsl:value-of select="last()+1 - position()"/> : <xsl:value-of select="name"/><br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
여기서 variable element에 대해 알아보자..
The <xsl:variable> Element
--------------------------------------------------------------------------------
Definition and Usage
The <xsl:variable> element is used to declare a local or global variable.
Note: The variable is global if it's declared as a top-level element, and local if it's declared within a template.
Note: Once you have set a variable's value, you cannot change or modify that value!
Tip: You can add a value to a variable by the content of the <xsl:variable> element OR by the select attribute!
--------------------------------------------------------------------------------
Syntax
<xsl:variable name="name" select="expression">
<!-- Content:template -->
</xsl:variable>
Attributes
Attribute Value Description
name name Required. Specifies the name of the variable
select expression Optional. Defines the value of the variable
Example 1
If the select attribute is present, the <xsl:variable> element cannot contain any content. If the select attribute contains a literal string, the string must be within quotes. The following two examples assign the value "red" to the variable "color":
<xsl:variable name="color" select="'red'" />
<xsl:variable name="color" select='"red"' />
Example 2
If the <xsl:variable> element only contains a name attribute, and there is no content, then the value of the variable is an empty string:
<xsl:variable name="j" />
Example 3
The following example adds a value to the variable "header" by the content of the <xsl:variable> element:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:variable name="header">
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</xsl:variable><xsl:template match="/">
<html>
<body>
<table>
<xsl:copy-of select="$header" />
<xsl:for-each select="reference/record">
<tr>
<xsl:if category="XML">
<td><xsl:value-of select="element"/></td>
<td><xsl:value-of select="description"/></td>
</xsl:if>
</tr>
</xsl:for-each>
</table>
<br />
<table>
<xsl:copy-of select="$header" />
<xsl:for-each select="table/record">
<tr>
<xsl:if category="XSL">
<td><xsl:value-of select="element"/></td>
<td><xsl:value-of select="description"/></td>
</xsl:if>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template></xsl:stylesheet>
[자료출처 : http://www.w3schools.com/xsl/el_variable.asp ]
w3school에서 이해하기 쉽게 예문을 만들어 주었다.
variable은 크게 두가지로 정의 할 수 있다.
단일 Tag 형태로..
<xsl:variable name="AAA" select="'안녕하세요...'"/>
Tag의 묶음인 블럭형 Tag로...
<xsl:variable name="header">
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</xsl:variable>
위 퍼온 글중에 파란색으로 표시한 부분이 있는데... variable의 속성을 잘 설명해 주고 있다.
한 번 읽어보자...
읽어봤다면 삽질을 덜 했겠지만 위에 적혀있는데로의 속성을 갖는다.
1. 기본속성
정말로 root element를 부르기 전에 최상단에서 정의 해주면 global의 성격을 갖는다.
어떤방식으로든 <xsl:template 안에서 불려지게되면 그 template를 벗어나게되면 변수값을 상실한다.
2. 변수명
한글이 지원된다. 고급 프로그래머에겐 큰 도움이 되진 않겠지만 어쨌든 된다.
변수명을 한글자나 혹은 XML이나 HTML에서 선언된 예약어와 겹치게 만들진 말았으면 한다.
설마 했다가 에러가 난다... 물론 변수명을 바꾸면 제대로 실행되는데도 말이다...
3. 변수타입을 식별해야한다.
XPath 함수중에 count() 라는 함수가 있다.
이 친구는 함수안에 노드이름을 넣어주면 표현한 XPath 값에 해당되는 노드가 몇 개 있는지 값을 숫자로 반환해준다. 다음과 같은 XML문서가 있다고 하자..
<XMLDocument>
<item>
<messege>야호</message>
</item>
<item>
<messege>안녕</message>
</item>
</XMLDocument>
root node로 XMLDocument가 해당되겠고
item은 XMLDocument의 자식이자 message의 부모이다.
여기서 item 노드의 갯수를 새고 싶다면 다음과 같이 하면된다.
1.
<xsl:template match="/">
<xsl:value-of select="count(item)"/>
</xsl:template>
2.
<xsl:template match="/XMLDocument">
<xsl:value-of select="count(item)"/>
</xsl:template>
3.
<xsl:template match="/">
<xsl:value-of select="count(XMLDocument/child::item)"/>
</xsl:template>
잠깐 표현형태에 대해서 알아봤고 다시 본론으로가서...
item이란 문자를 변수로 만들어서 쓰면 좋겠다 싶어서 그렇게 해봤다.
<xsl:template match="/">
<xsl:variable name="Tmp" select="'item'"/>
<xsl:value-of select="count($Tmp)"/>
</xsl:template>
이렇게 하면 에러가 난다...
<xsl:template match="/">
<xsl:variable name="Tmp" select="'item'"/>
<xsl:variable name="Tmp2">{$Tmp}</xsl:variable>
<xsl:value-of select="count($Tmp2)"/>
</xsl:template>
다음과 같이 변수를 Tag 확장을 통해서 직접 적어줄 수 있는 { } 를 이용하면 에러가 나진 않는다. 하지만 제대로된 노드의 count 값을 주지 못한다.
Tmp변수에 절대경로 XPath값인 XMLDocument/child::item 값을 주어보았다..
<xsl:template match="/">
<xsl:variable name="Tmp" select="'XMLDocument/child::item'"/>
<xsl:variable name="Tmp2">{$Tmp}</xsl:variable>
<xsl:value-of select="count($Tmp2)"/>
</xsl:template>
결과는 마찬가지...
반드시 다음과 같이 해야만 에러가 나지 않는다.
<xsl:template match="/">
<xsl:variable name="Tmp" select="XMLDocument/child::item"/>
<xsl:value-of select="count($Tmp)"/>
</xsl:template>
문자열이 아닌 노드값을 변수를 직접적으로 주어야 한다.
XSLT는 변수를 선언할 때 노드를 변수로 받을 수 있다.
count() 함수는 반드시 노드값 만을 count 할 수 있다.
게다가...
XMLDocument/child::item
이 노드경로 문자열을 concat() 함수등으로 붙여서 문자열로 만들어준 뒤에 집어넣어주면 변수는 노드경로로 인식하지 못한다.
노드값을 변수로 지정하고 싶다면 반드시 조작없이 입력을 해야 한다.
적어도 XSLT문서 내에서는 불가능 하다.
4. 변수를 덮어쓰지(modify) 못한다.
변수를 선언함에 있어서 변수에 변수를 덮어쓰는... 예를 들어...
$a++;
를 구현하기위해서...
<xsl:variable name="a" select="1"/>
<xsl:variable name="a" select="$a +1"/>
이런식의 프로그래밍은 절대로 되지 않는다.
변수를 자유롭게 가공하는데 익숙한 사람이라면 뜻 데로 되지 않아 좀 타격을 입을 수 있는 부분이라 하겠다. (-_-;)
물론 노드 집합이 아닌 데이터에 대해서는 position()같은 XPath 함수가 있지 않기에 손쉽게 loop를 돌리기 힘들다.
XSLT의 variable element에 대해서 알아보았다.
XSLT에선 변수속에 변수를 담아낼 수 있지만 단일 변수에선 불가능하다.
어쨌든 선언만 하면 끝이 난단 소린데...
이를 조작하기 위해선 <xsl:template> 과 <xsl:call-template> 가 필요하다.
일종의 함수같은 기능을 하는 template는 template 속에 template을 담아서 확장할 수 있다.
다만 삽질을 할 확률이 높은 부분이 있는데 함수의 return 값을 주듯이 template에서 사용한 모든 변수를 반드시 반환해줘야만 한다는 점이다.