XSLT Quickly 요약

★ XSL 기본 헤더와 푸터

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

...내용...

</xsl:stylesheet>

★ p.40 속성 바꾸기

<wine price="1" year="1997">Carneros</wine>

↓

<wine vintage="1997">Carneros</wine>

<xsl:template match="wine">

<wine vintage="{@year}">

<xsl:apply-template/>

</wine>

</xsl:template>

속성이나 요소를 삭제할때는 그냥 언급을 회피하면 될뿐...
@문자는 지정한 이름을 가지는 속성의 값을 의미한다.

{} 중괄호는 XSLT가 그 안의 내용을 글자 그대로 가져오지 않고 수식으로서 연산 한 뒤에
가져오도록 지정하는 것이다. {2 + 2}라고 하면 4가 들어가게 된다.

★ p.41 속성과 요소간의 변환

<wine grape="Chardonnay">

<product>Carneros</product>

<year>1997</year>

<price>10.99</price>

</wine>

↓

<wine vintage="1997">

<product>Carneros</product>

<category>Chardonnay</category>

<price>10.99</price>

</wine>

<xsl:template match="wine">

<wine vintage="{year}">

<product><xsl:apply-templates select="product"/></product>

<category><xsl:value-of select="@grape"/></category>

<price><xsl:apply-templates select="price"/></price>

</wine>

</xsl:template>

★ p.42 속성값에 따라 요소 선택하기
어떤 요소가 특정 속성을 가질때만 선택하기

<xsl:template match="wine[@grape='Cabernet']">

<xsl:copy><xsl:apply-templates/></xsl:copy>

</xsl:template>

★ p.50 XPath의 로케이션 스텝
child::wine[last()]
축 ::노드테스트[프레디케이트]
Axis ::NodeTest[Predicate]

필수 로케이션 스텝은 노드뿐이다.
축은 보통 생략되는 child로 간주되고 프레디케이트는 조건을 줘서 조건에 맞는 노드만을 취사
선택하는데에 사용한다.
프레디케이트는 문서의 맨위부터 따지는 것이 아니라 현재 컨텍스트 노드 자신과 가까운쪽이 1
가장 먼쪽이 last()가 된다.

★ p.50 컨텍스트(Context) 노드란?
현재 처리중인 노드를 의미한다.

★ p.51 축(Axis)?
축 한정자는 선택될 노드와 컨텍스트 노드 사이의 위치 관계를 지정한다.
종류 :

child, descendant, parent, ancester, following-sibling, preceding-sibling,

following, preceding, attribute, name-space, self, descendant-or-self, ancestor-or-self

★ p.52 부모 노드의 속성을 표시하기

<wine grape="Cabernet">

<year>1998</year>

<prices>

<list>13.99</list>

<discounted>11.99</discounted>

</prices>

</wine>

현재 컨텍스트 노드가 prices 일때, 여기에 부모노드(<wine>)의 속성을 표시하려면,

<xsl:template match="prices">

parent element's grape:

<xsl:value-of select="parent::wine/attribute::grape"/>

</xsl:template>

parent와 attribute는 각각 .. 와 @ 로 축약해서 표현할 수 있다.

<xsl:template match="prices">

parent element's grape:

<xsl:value-of select="../@grape"/>

</xsl:template>

★ p.53 child 축의 축약형
XPath에서 축이 생략되면 무조건 child 축의 생략으로 간주한다.

<wine>을 처리하는 도중 그의 자식노드인 year의 값을 가져오려면,

<xsl:template match="wine">

<wine vintage="{child::year}">

</xsl:template>

혹은, 축 한정자가 생략되면 무조건 child로 간주하므로,

<xsl:template match="wine">

<wine vintage="{year}">

</xsl:template>

{year}부분을 <xsl:value-of select="year"/>를 이용할 수 는 없다.

★ p.53 수식의 처리
수식을 계산하거나 어떤 노드의 값을 <xsl:value-of/>가 아닌 방법으로 얻으려면
{}사이에 넣으면 된다.
{}내부에 있는 값을 계산된뒤에 입력된다.

★ p.55 ancestor 축

<A>

<B>

<C/>

</B>

</A>

가 있을때 <C>의 ancestor는 <A>, <B>를 의미한다.
ancester:A 와 같은 형식으로 지정하면 된다.

★ p.56 ancestor-or-self 축

<A>

<B>

<C/>

</B>

</A>

가 있을때 <C>의 ancestor-or-self는 <A>,<B>,<C>이다.

★ p.56 자기 자신 혹은 자기의 부모가 가진 특정 속성의 값을 조건으로 줄때,

<xsl:template matching="waring">

<xsl:if test="ancester-or-self::*[@xml:lang][1]/@xml:lang='en'">

<p>Warning!</b><xsl:apply-templates/></p>

</xsl:if>

</xsl:template>

이 경우, 아래부터 위로 검색해나간다.
<C>의 위치에서 먼저 <B>를 검사하고 그 다음에 <A>를 검사하므로 만약 xml:lang 속성이 B 와
A에 있을 경우 xml:lang[1]은 B위치의 속성이 검사되게 된다. xml:lang[last]는 A위치의
속성이된다.

★ p.58 preceding-sibling / following-sibling
자기와 동일한 부모 밑에 있는 노드들 중, preceding-sibling은자기보다 위에 속한 것들이고
following-sibling은 자기보다 아래에 속한 것들이다.

<story>

<chapter>

<title>A</title>Contents A</chapter>

<chapter>

<title>B</title>Contents B</chapter>

<chapter>

<title>C</title>Contents C</chapter>

</story>

↓

chapter

Prev:

Next: B

chapter

Prev: A

Next: C

chapter

Prev: B

Next:

위와 같이 하려면...

<xsl:template match="chapter">

<h3>chapter</h3>Prev: <xsl:value-of select="preceding-sibling::chapter[1]/title"/><br/>

Next: <xsl:value-of select="following-sibling::chapter/title"/>

<xsl:value-of select="./text()"/><br/>

</xsl:template>

preceding-sibling이 프레디케이트를 계산할 때는 자기와 가까운 쪽, 즉 자기 바로 위를 1로
하고, 자기와 가장 먼 맨 위의 것을 last()로 한다.

★ p.61 preceding과 following
preceding 축은 문서의 처음부터 컨텍스트 노드 바로 이전까지, following은 컨텍스트 노드 바로
다음부터 문서의 끝까지의 모든 노드를 의미한다. 형제, 부모 할것 없이 다 포함한다.
프레디케이트는 자신과 가까운쪽이 1이다.

<A>

<B>

<C><TITLE>1</TITLE><T/></C>

<C><TITLE>2</TITLE><D><T/></D></C>

<C><TITLE>3</TITLE><C>

<B>

<A>

첫번째 <T>는 <C>의 자식이고 두번째 <T>는 <D>의 자식이다. 여기서 1과 3을 얻으려면,

<xsl:template match="test">

<xsl:value-of select="preceding::C[1]/TITLE"/>

<xsl:value-of select="following::C/TITLE"/>

</xsl:template>

★ p.65 descendant와 descendant-or-self
descendant는 컨텍스트 노드의 자식들과 그 자식들의 자식들 등, 컨텍스트 노드의 모든 자식들을
의미한다. descendant-or-self는 말 그대로 자신을 포함한 자손들.

<xsl:for-each select="descendant::figure">

<xsl:value-of select="title"/>

</xsl:for-each>

이것은 자기 아래에 있는 모든 figure 노드에서 title 요소의 값을 가져온다.

<xsl:for-each select="descendant-or-self::*/@author">

<xsl:value-of select="."/>

</xsl:for-each>

자기 자신을 포함하여 그 자식 모두를 검사하여 author 속성의 값을 출력한다.

★ p.69 descendent-or-self 의 축약

descendent-or-self::node() 는 // 로 표현될 수 있다.

chapter//title 은 chapter 요소의 자손 중에서 title이라는 이름을 가진 모든 요소를 의미한다.

단지 //요소 로만 쓰이면 문서의 루트에 대한 모든 자손들을 의미한다. 예를들어 //title은 문서 전체에서 모든 title 요소를 의미한다.

chapter//@author 는 chapter와 그 자손들의 author 속성을 의미한다

chapter//comment()는 문서에 속한 모든 주석을 의미한다.

★ p.70 self
self 는 컨텍스트 노드 그 자신이다.
이것의 축약은 . 으로 self:node()를 의미한다.

★ p.70 namespace
이것은 기본 xml 네임스페이스와 컨텍스트 노드의 범위 안에 있는 모든 네임스페이스로
구성된다. (표준은 xml 네임스페이스를 포함해야 하지만 그렇지 않은 것도 있다.)

<xsl:template match="test">

<xsl:for-each select="namespace::*">

<xsl:value-of select="name()"/>

<xsl:text>

</xsl:text>

</xsl:for-each>

★ p.72 노드 테스트(Node test)
* 은 모든 요소(Element) 노드를 의미한다.
node() 는 종류에 상관없는 모든 노드를 의미한다. 이것은 주석이나 PI등도 포함한다.

<xsl:for-each selec="node()">

<xsl:value-of select="." />

</xsl:for-each>

★ 프레디케이트(Predicate)
프레디케이트는 참/거짓의 값만 가진다.

child::wine[@grape] : grape 속성을 가진 모든 wine요소. grape의 값은 상관없다.
child::wine[year] : year 요소를 가진 wine.
child:wine[4] : 4번째 wine 요소. 이것은 child:wine[position() = 4]의 축약이다.
last() 선택된 것중 마지막 노드
text() 텍스트로 된 내용을 가지고 있는 모든 노드.
not() 조건식의 결과를 뒤집는다. not(text()), child:wine[not(@grape)]

★ p.77 손자 노드의 조건에 따라 자식 노드의 값출력

<xsl:template match="winelist">

Wines:needing their "discount" value set;

<xsl:for-each select="wine/prices/discounted[not(text())]">

<xsl:value-of select="../../year"/><xsl:text> </xsl:text>

<xsl:value-of select="../../winery"/><xsl:text </xsl:text>

</xsl:for-each>

</xsl:template>

★ p.83 동적으로 태그 생성
<xsl:element name="ode">내용</xsl:element>
이것은 <ode>내용</ode>를 생성한다.

이것을 이용해 정해지지 않은 동적 태그 생성이 가능해진다. 다음은 peom의 type 속성에 따라 동적으로 태그를 생성한다.

<xsl:template match="poem">

<xsl:element name="{@type}">

<author>John Milton</author>

<year><xsl:value-of select="@year"/></year>

</xsl:element>

</xsl:template>

★ p.84 <xsl:apply-templates>는 현재 노드의 자식 노드만을 다룬다.
이것은 자식 노드들이 <xsl:template>을 갖고 있지 않을 경우 그 노드의 값을 취해서
추가해준다. 이것을 내장 템플릿 룰이라고 한다.

★ p.86 부모, 자식, 형제의 값 얻기, 노드의 이름얻기

<xsl:template match="list">

~~~~~ Start of list element's template ~~~~~

1. List price (current node) : {<xsl:apply-templates/>}

2. Parent element (price) : {<xsl:value-of select=".."/>

3. Grandparent element contents : {<xsl:value-of select="../.."/>}

4. Attribute of grandparent : {<xsl:value-of select="../../@grape"/>}

5. Sibling node {<xsl:value-of select="../discounted"/>}

6. "Uncle" node {<xsl:value-of select="../../product"/>}

7. Parent node's name: {<xsl:value-of select="name(..)"/>}

8. Grandparent node's name: {<xsl:value-of select="name(../..)"/>}

~~~~~ End of list element's template ~~~~~

</xsl:template>

★ p.89 정해지지 않은 자기 형제 참조

<xsl:template match="item[3]">

~~~ Start of item element's template ~~~

1. This node : {<xsl:apply-templates/>}

2. First node : {<xsl:value-of select="../item[1]/>}

3. Last node : {<xsl:value-of select="../item[last()]"/>}

4. Preceding node : {<xsl:value-of select="preceding-sibling::item[1]"/>

5. Next node : {<xsl:value-of select="following-sibling::item[1]"/>}

6. flavor attriute value of first node : {<xsl:value-of select="../item[1]/@flavor"/>}

~~~ End of item element's template ~~~

xsl:value-of는 기본적으로 선택된 노드들 중 첫번째 것만 반환한다.

★ p.92 요소를 속성으로 변환하기
" " 내에 <xsl:value-of>를 쓸 수 없다. 그 대신 다음과 같이 사용한다.

<xsl:template match="wine">

<wine variental="{@grape}" brand="{winery}" year="{../year}"/>

</xsl:template>

★ p.96 요소를 복사하며 속성 추가
<xsl:copy>가 단독으로 쓰이면 컨텍스트 노드의 요소 이름만 복사될 뿐이다. 즉, 태그만
복사되고 태그의 내용은 복사되지 않는다.

다음은, <xsl:copy>와 다른 명령으로 속성과 내용을 복사하는 것이다.

<xsl:copy>

<xsl:attribute name="date"> <!-- 이것이 속성을 추가해 주는 것이다. -->

<xsl:value-of select="@date"/>

</xsl:attribute>

<xsl:apply-templates/> <!-- 내용복사 -->

</xsl:copy>

★ p.96 컨텍스트 노드를 자식과 속성까지 완전하게 그대로 복사하기
자식과 요소는 물론 PI와 주석, 네임스페이스 등까지 복사한다.

<xsl:template match="wine">

<xsl:copy-of select="."/>

</xsl:template>

★ p.100 노드의 개수 세기
count() 함수를 이용한다.

<xsl:template match="employees">

A. Number of employees:

<xsl:value-of select="count(employee)"/>

B. Number of officers:

<xsl:value-of select="count(employee[@officer='yes'])"/> <!-- 'yes' 작은 따옴표! -->

C. Number of employees without 'officer' attribute set:

<xsl:value-of select="count(employee[not(@officer)])"/>

D. Number of comments in 'employees' element:

<xsl:value-of select="count(//comment())"/> <!-- 모든 주석의 개수 -->

</xsl:template>

★ p.103 apply-templates 에서 처리할 노드를 직접 지정하기

<xsl:template match="customer">

<client>

<xsl:apply-templates select="lastName"/>

<xsl:apply-templates select="phone"/>

</client>

</xsl:template>

만약 여기서 그냥 <xsl:apply-templates/>를 한다면 모든 customer의 자식 노드들의 내용이
여기에 삽입될 것이다. 여기서는 lastName과 phone에만 템플릿을 적용하여 두 자식 노드들의
값만 가져오도록 한다.

★ p.104 동일한 내용(text())를 가진 요소 제거

<sample>

<line lid="u1">hello</line>

<line color="red" lid="u2">hello</line>

<line color="blue" lid="u3">hello</line>

<line lid="u4">hello there</line>

<line color="blue" lid="u5">hello there</line>

<line color="blue" lid="u6">hello</line>

</sample>

↓

<sample>

<line lid="u1">hello</line>

<line lid="u4">hello there</line>

</sample>

속성은 아무 관계 없이 노드의 내용이 동일한 것을 제거하려면

<xsl:template match="line">

<xsl:if test="not(. = preceding::line)">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/> <!-- 속성과 노드의 내용 복사 -->

</xsl:copy>

</xsl:if>

</xsl:template>

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

★ p.105 동일한 속성을 가진 요소 제거

<xsl:template match="line">

<xsl:if test="not(@color = preceding::line/@color)">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:if>

</xsl:template>

not(@color = preceding::line/@color) 는 컨텍스트 노드의 color 속성의 값과 현재 노드 위쪽에
존재하는 line 요소의 color 속성을 비교하여 다르면 참을 리턴한다.

★ p.106 요소와 속성을 동시에 비교하기

<xsl:template match="line">

<xsl:variable name="contents" select="."/>

<xsl:variable name="colorVal" select="@color"/>

<xsl:if test = "not(preceding::line[(. = $contents) and (@color = $colorVal)])">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:if>

</xsl:template>

not(preceding::line(. = $contents) and (@color = $colorVal)]) 에서 .은 preceding::line
노드를 의미하고, @color 는 preceding::line의 color 속성을 의미한다.

★ p.109 이 노드는 비어 있는가? (text()가 없는가?)

<xsl:template match="sample">

<xsl:choose>

<xsl:when test="normalize-space(.)">

Sample element <xsl:value-of select="@eid"/> isn't empty.

</xsl:when>

<xsl:otherwise>

Sample element <xsl:value-of select="@eid"/> is empty.

</xsl:otherwise>

</xsl:choose>

</xsl:template>

normalize-space(node)는 노드 집합을 문자열로 전환한 후 여러 공백을 하나로 바꾸고, 문자열
앞뒤의 공백을 잘라낸 뒤 문자가 남아 있으면 true 그렇지 않으면 false 이다.

★ p.116 특정 자식을 갖고 있는 요소의 템플릿

<xsl:output method="text"/>

<xsl:strip-space elements="*"/>

<xsl:template match="setc2[figure]"> <!-- figure라는 자식 노드가 있는가? -->

<xsl:value-of select="title"/>

[<xsl:apply-templates/>]

</xsl:template>

★ p.117 노드 내용에 특정한 문자열을 포함한 요소는?

<xsl:template match="para[contains(.,'the')]"> <!-- contains()의 . 을 주의하라. -->

** This para has "the" in it: ***

<xsl:apply-templates/>

</xsl:template>

문자열이 자식 노드에 포함되어 있어도 마찬가지 이다.

★ p.121 새로운 요소와 그 요소의 속성 추가하기

<xsl:template match="verse">

<xsl:element name="line"> <!-- <line> 태그가 생성된다. -->

<xsl:attribute name="status">done</xsl:attribute> <!-- <line status="done">

<xsl:attribute name="hue">

<xsl:value-of select="@color"/>

</xsl:attribute> <!-- <line status="done" hue="@color의 값">

<xsl:attribute name="number">

<xsl:value-of select="amount"/>

</xsl:attribute>

<xsl:attribute name="sourceElement">

<xsl:text>src</xsl:text><xsl:value-of select="generate-id()"/>

</xsl:attribute>

</xsl:element>

</xsl:template>

최종 생성 태그는 <line status="done" hue="@color" number="5" sourceElement="srcb2a"/>

★ p.124 속성의 이름과 값 얻기

<para color="blue" flavor="mint" author="bd">Here is a paragraph.</para>

↓

Color : blue

attribute name: color

attribute value: blue

attribute name: flavor

attribute value: mint

attribute name: author

attribute value: bd

위와 같이 속성의 이름과 값을 얻으려면,

<xsl:template match="para">

Color : <xsl:value-of select="@color"/>

<!-- list the attribute names and values. -->

<xsl:for-each select="@*">

attribute name: <xsl:value-of select="name()"/>

attribute value: <xsl:value-of select="."/>

</xsl:for-each>

</xsl:template>

★ p.126 속성의 존재 여부. 속성이 특정한 값을 가지고 있는가?

<para color="blue" flavor="mint" author="jm">Here is a paragraph.</para>

↓

There is a flavor attribute

Athor equals "jm"

<xsl:template match="para">

<xsl:if test="@flavor">There is a flavor attribute</xsl:if>

<xsl:if test="@font">There is a font attribute</xsl:if>

<xsl:if test="@author = 'jm'">Author equals "jm"</xsl:if>

</xsl:template>

★ p.127 속성 그룹(Attribute set) 사용하기
속성 그룹을 만들고 어떤 요소에 한꺼번에 추가시켜 줄 수 있다.

<xsl:attribute-set name="lineAttrs">

<xsl:attribute name="status">done</xsl:attribute>

<xsl:attribute name="hue">

<xsl:value-of select="@color"/> <!-- 디폴트값. 디폴트 값은 무시될 수 있다. -->

</xsl:attribute>

<xsl:attribute name="number>

<xsl:value-of select="amount"/>

</xsl:attribute>

<xsl:attribute name="sourceElement">

<xsl:text>src</xsl:text><xsl:value-of select="generate-id()"/>

</xsl:attribute>

</xsl:attribute-set>

<xsl:template match="verse">

<xsl:element name="line" use-attribute-sets="lineAttrs">

<xsl:attribute name="author">BD</xsl:attribute> <!-- 디폴트 값을 무시함 -->

<xsl:attribute name="hue">NO COLOR</xsl:attribute> <!-- 디폴트 값을 무시함 -->

</xsl:apply-templates>

</xsl:element>

</xsl:template>

★ p.129 HTML 주석 출력하기

<xsl:template match="poem">

<html>

<xsl:comment>Created By FabAutoDocGen release 3</xsl:comment>

<xsl:apply-template>

</html>

</xsl:template>

★ p.131 HTML 주석 사이에 노드의 값 출력하기

<xsl:template match="documentation">

<xsl:comment><xsl:apply-templates/></xsl:comment>

</xsl:template>

★ p.131 XML파일 자체의 주석 이용하기

<xsl:template match="comment()">

<xsl:comment><xsl:value-of select="."/></xsl:comment>

</xsl:template>

★ p.136 결과 트리에 엔티티 레퍼런스 삽입

<!DOCTYPE stylesheet [

ENTITY ntilde "ñ"

]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="test">

<testOut>

The Spanish word for "Spain" is "España".

<xsl:apply-templates/>

</testOut>

</xsl:template>

</xsl:stylesheet>

스타일시트에 기본적으로 미리 선언된 다섯개의 엔티티(lt, gt, apos, quot, amp)외의 다른
엔티티를 참조하고자 한다면, 그것들을 DOCTYPE 선언부에 직접 선언해 주어야 한다.

★ p.138 엔티티 레퍼런스 자체를 삽입히기

<!DOCTYPE stylesheet [

ENTITY ntilde

"<xsl:text disable-output-escaping='yes'>ñ</xsl:text>"

]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output doctype-system="testOut.dtd"/>

<xsl:template match="test">

<testOut>

The Spanishword for "Spain" is "España"

<xsl:apply-templates/>

</testOut>

</xsl:template>

</xsl:stylesheet>

España 가 이 모양 그대로 출력된다.

★ p.142 Namespace 지정
"xsl"을 XSLT 요소임을 나타내는 접두사로 사용하는 것은 단지 관례일 뿐이다. 다른 것을
지정해도 된다.

<harpo:stylesheet

xmlns:harpo="http://www.w3.org/1999/XSL/Transform"

version="1.0">

<harpo:output method="xml" omit-xml-declaration="yes"/>

<harpo:template match="xdata">

<heading>xdata</heading><harpo:text>

</harpo:text>

<text><harpo:apply-templates/></text>

</harpo:template>

</harpo:stylesheet>

★ p.147 XML문서를 XSLT로 변환하려면

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xslAlt="http://www.snee.com/xml/dummy"

version="1.0">

<!-- xslAlt를 xsl로 바꿔 출력하라 -->

<xsl:namespace-alias stylesheet-prefix="xslAlt" result-prefix="xsl"/>

<xsl:template match="elementHandler">

<!-- 아래는 <xsl:template match="@element값"> 으로 출력된다. -->

<xslAlt:template match="{@element}">

<xsl:apply-templates/>

</xslAlt::template>

</xsl:template>

<xsl:template match="elementContents">

<xslAlt:apply-templates/>

</xsl:template>

<xsl:template match="ssheet">

<xslAlt:stylesheet version="1.0">

<xsl:apply-templates/>

</xslAlt:stylesheet>

</xsl:template>

<!-- Just copy any other elements, attributes, etc. -->

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

</xsl:stylesheet>

★ p.156 해석 불가능한 엔티티(JPG 파일등)의 URI추가

<xsl:template match="picture">

<img src=http://img.yahoo.co.kr/blank.gif>

</xsl:template>

picfile 이 XML파일에 다음과 같이 지정되어 있다면

ENTITY ceres SYSTEM "../pics/cerespic.jpg" NDATA JPEG

생략..

<picture picfile="ceres"/>

★ p.159 PI 출력

<xsl:template match="article">

<xsl:processing-instruction name="xml-stylesheet">

<xsl:text>href="headlines.css" type="text/css"</xsl:text>

</xsl:processing-instruction>

<html>

<xsl:apply-templates/>

</html>

</xsl:template>

위의 결과는

<?xml-stylesheet href="headlines.css" type="text/css"?>

xsl:processing-instruction이 트리의 최상위에 위치해서는 안된다. 만약 그것이
xsl:stylesheet 요소의 자식이라면, XSLT 프로세서는 그것을 무시한다.

★ p.161 원본 트리에서 PI 읽고 이용하기

<xsl:template match="processing-instruction()">

<xsl:copy/>

<xsl:template>

좀더 세밀하게 이용하기

<?xml-stylesheet href="headlines.css" type="text/css"?>

<?smellPlugIn scent="newCar" duration="12secs"?>

와 같은 PI가 있을 때..

<xsl:template match="processing-instruction('xml-stylesheet')">

<style　　　　sheet><xsl:value-of select="."/></stylesheet>

</xsl:template>

<xsl:template match="processing-instruction('smellPlugIn')">

<smellData><xsl:value-of select="."/></smellData>

</xsl:template>

★ p.164 <xsl:if> 총정리

<xsl:template match="poem">

--- Start of "if" tests. ---

<xsl:if test="@author='jm'"> <!-- author 속성이 'jm'인가? -->

1. The poem's author is jm.

</xsl:if>

<xsl:if test="@author"> <!-- author 속성이 존재하는가? -->

2. The poem has an author attribute

</xsl:if>

<xsl:if test="verse"> <!-- verse 자식 요소를 가지고 있는가? -->

4. The poem has at least one verse child element.

</xsl:if>

<xsl:if test="count(verse) > 3"> <!-- 크다. 궂이 > 를 사용안해도 됨 -->

6. The poem has more than 3 verse child elements.

</xsl:if>

<xsl:if test="count(verse) < 3"> <!-- 작다. <를 사용하면 안되! -->

6. The poem has less than 3 verse child elements.

</xsl:if>

<!-- or 조건주기 -->

<xsl:if test="(@author = 'bd') or (@year='1667')>

8. Either the author is "bd" or the year is "1667".

</xsl:if>

<!-- 중첩 if -->

<xsl:if test="@year < '1850'">

9a. The poem is old.

<xsl:if test="@year < '1700'">

9b. The poem is very old.

</xsl:if>

<xsl:if test="@year < '1500'">

9c. The poem is very, very old.

</xsl:if>

</xsl:if>

</xsl:template>

* 템플릿에서 test 속성의 값에 사용된 큰 따옴표 안에 "jm"이라는 문자 데이터를 보호하기
위해 따옴표를 사용한 점을 주시하자. 뿐만 아니라 스트링 값을 구분하기 위해 """ 또는
"'"라는 엔티티 참조를 대신 사용할 수 있다. (예: test="@author="jm"")
* 만약 xsl:if 요소의 테스트 속성에서 "보다 작은(< 부등호를 사용하려면 "<"라는 엔티티
참조를 사용해야함을 잊지 말라.
* and/or 연산자를 사용할 수 있다.

★ p.169 <xsl:choose> 총정리

<xsl:template match="poem">

<xsl:choose>

<xsl:when test="@year < 1638">

The poem is one of Milton's earlier works.

</xsl:when>

<xsl:when test="@year < 1650">

The poem is from Milton's middle period.

</xsl:when>

<xsl:when test="@year < 1668">

The poem is one of Milton's later works.

</xsl:when>

<xsl:when test="@year < 1675">

The poem is one of Milton's last works.

</xsl:when>

<xsl:otherwise>

The poem was written after Milton's death

</xsl:otherwise>

</xsl:choose>

</xsl:template>

xsl:choose 는 최초로 조건을 만족시킨 부분만 실행하고 끝난다.

★ p.170 언제 중괄호{}를 사용하는가?

<xsl:template match="/">

<test>

<xsl:variable name="myVar">10</xsl:variable>

A. <atvtest at1="hello world"/>

B. <atvtest at1="3 + 2 + $myVar"/> <!-- 문자열로 취급됨 -->

C. <atvtest at1="{3 + 2 + $myVar"/> <!-- 식으로 취급됨 -->

D. <atvtest at1="u{3+2}"/> <!-- "u5" 출력 -->

E. <atvtest at1="yo, substring('hello world',7)"/> <!-- 문자열로 취급됨 -->

F. <atvtest at1="yo, {substring('hello world',7)"/> <!-- "yo, world" 출력 -->

</test>

</xsl:template>

★ p. 171 언제 중괄호{}를 사용하면 안되는가?

<xsl:variable name="myVar">10</xsl:variable>

A. <xsl:value-of select="3+2+$myVar"/> <!-- select 안의 내용은 수식으로 취급. {}불가 -->

B. <xsl:value-of select="substring('hello world', 7)"/>

★ p.176 <for-each>를 이용한 목차 만들기
xsl:for-each 명령은 주어진 노드들의 집합에 대하여 같은 명령을 반복적으로 실행시킨다. 이들
노드들을 명시할 때에는 XPath의 축 한정자, 노드 테스트, 프레디케이트 구문들을 그대로 사용할
수 있다.

<xsl:template match="chapter">

Pictures:

<xsl:for-each select="descendant::figure">

<xsl:value-of select="title"/><xsl:test>

</xsl:test>

</xsl:for-each>

Chapter:<xsl:apply-templates/>

</xsl:template>

이것은 figure 요소의 title 자식요소들을 모두 가져다가 화면에 표시해준다.

★ p.177 for-each 와 XPath
xsl:tmeplate 요소의 match 속성에 XPath 표현을 사용할 수 있지만, 사실 그 XPath는 패턴이라고
알려진 XPath의 부분집합이라는 제한을 가지고 있는 반면에, xsl:for-each 요소의 select
속성에는 완벽한 XPath 표현이 가능하다.

<xsl:template match="title">

<xsl:text>title ancestors:</xsl:text>

<xsl:for-each select="ancestor::*">

<xsl:value-of select="name()"/>

<xsl:if test="position() != last()">

<xsl:text>,</xsl:text>

</xsl:if>

</xsl:for-each>

</xsl:template>

<xsl:template match="para"/>

xsl:value-of 에게 어떤 노드들의 집합을 가져오게 하면 그것은 단지 그 무리에 있는 첫 번째
노드의 문자열 형식만을 던져준다는 점이다. 이에 반해 xsl:for-each는 마찬가지로 어떤
노드들의 집합을 가져오게 하면 그 집합 전체를 가져다 준다.

★ p.180 재귀 호출을 통한 템플릿 반복 수행

<xsl:template name="hyphens">

<xsl:param name="howMany">1</xsl:param>

<xsl:if test="$howMany > 0">

<xsl:text>-</xsl:text>

<xsl:call-template name="hyphens">

<xsl:with-param name="howMany" select="$howMany - 1"/>

</xsl:call-tempalte>

</xsl:if>

</xsl:template>

<xsl:template match="sample">

Print 1 hyphen:

<xsl:call-template name="hyphens"/>

<xsl:with-param name="howMany" select="3"/>

</xsl:call-template>

Print 20 hyphens:

<xsl:call-template name="hyphens">

<xsl:with-param name="howMany" select="20"/>

</xsl:call-template>

Print 0 hyphens:

<xsl:call-template name="hyphens">

<xsl:with-param name="howMany" select="0"/>

</xsl:call-tempalte>

</xsl:template>

재귀 호출에서 중요한 것은 재귀 호출을 멈출 조건이 언젠가는 반드시 참이 되어야 한다는
것이다.

★ p.184 <xsl:include> 다른 XSL 문서 포함하기

<xsl:include: href="inlines.xsl"/>

<xsl:template match="chapter">

.... 생략

inlines.xsl이 통째로 들어간 것은 아니고, 그 내용만 들어갔다. 다시 말해 그 스타일 시트의
xsl:stylesheet 태그들 사이의 모든 것들이 이 XSL내용에 끼어들어간다.

포함시킨 스타일시트의 부분이 그 자체로서 하나의 완전한 스타일시트가 되어야 한다.

포함 관계 중에 자기 자신이 있으면 그것은 에러이다.

xsl:include 요소가 top-level요소 즉, 스타일시트의 주 몸체를 만드는 xsl:stylesheet 요소의

자식 요소이면 스타일시트의 어느 곳에도 올 수 있다.

★ p.186 <xsl:import> 다른 XSL 문서 포함하기
xsl:import는 임포트 시키는 스타일시트에서 임포트된 스타일시트의 명령어들을 재정의할 수
있다. 그 외엔 xsl:include와 동일하다.

<xsl:import href="inlines.xsl"/>

xsl:import 요소는 스타일시트의 XSLT 네임스페이스에 속하는 다른 어떤 요소보다도 앞에 와야

한다.

★ p.192 이름을 가진 템플릿
템플릿에 이름을 주고 마치 함수처럼 호출 할 수 있다.

<xsl:template name="boldIt"> <!-- 템플릿에 이름을 주었다. -->

<b><xsl:apply-templates/></b>

</xsl:template>

<xsl:template match="winery">

<p><xsl:call-template name="boldIt"/></p> <!-- 템플릿 호출!! -->

</xsl:template>

<xsl:template match="product">

<p><xsl:call-template name="boldIt"/></p>

</xsl:template>

<xsl:template match="year | price">

<p><xsl:apply-templates/></p>

</xsl:template>

★ p.194 <xsl:message>를 이용한 디버깅

<xsl:param name="bodyTextSize">10pt</xsl:param>

<xsl:template match="/">

<xsl:if test="$bodyTextSize != '10pt'">

<xsl:message>bodyTextSize default value overridden with value of

<xsl:value-of select="$bodyTextSize"/>.

</xsl:message>

</xsl:if>

</xsl:appl-templates>

</xsl:template>

xsl:message 의 출력 내용은 XSLT변환의 출력으로 가지 않고 화면에 나온 다든지의 XSLT
프로세서에 따라 다르다.

★ p.196 XSLT 프로세서 실행 멈추기

<xsl:template match="/">

<xsl:if test="not(contains($bodyTextSize, 'pt'))">

<xsl:message terminate="yes">bodyTextSize must be specified in points

(pt).</xsl:message>

</xsl:if>

<xsl:apply-templates/>

</xsl:template>

★ p.199 템플릿으로 처리하지 않고 지나쳐 버린 요소 확인하기

<xsl:template match="*">

<h1><xsl:value-of select="name()"/> ELEMENT UNACCOUNTED

FOR BY STYLESHEET: <xsl:apply-templates/></h1>

</xsl:template>

다른 템플릿에 의해 처리되지 않은 모든 요소들이 <xsl:template match="*">에 의해 처리된다.

★ p.209 확장 요소가 지원되는지 확인하기
XSLT 프로세서가 특정 확장 요소를 구현하지 않았다면, 프로세서는 xsl:fallback 요소의 자식
요소를 찾아 결과 트리에 붙인다.

<saxon:assing name="color">blue<xsl:fallback>

<xsl:message>This XSLT processor doesn't support saxon:assign.

</xsl:message></xsl:fallback>

</saxon:assing>

다른 방법으로 element-available()을 사용한다.

<xsl:choose>

<xsl:when test="element-available('saxon:assign')">

<saxon:assign name="color">blue</saxon:assign>

</xsl:when>

<xsl:otherwise>

<xsl:message>This XSLT processor  doesn't support saxon:assign.

</xsl:message>

</xsl:otherwise>

</xsl:choose>

★ p.211 내장 확장 함수 사용
확장함수가 지원되는지 확인 한 뒤에 사용하기

<xsl:choose>

<xsl:when test="function-available('xalan:tokenize')">

<xsl:for-each select="xalan:tokenize(.,',')">

<entry><xsl:value-of select="."/></entry>

</xsl:for-each>

</xsl:when>

</xsl:choose>

★ p.213 산술 연산 예제(숫자 계산)

<numbers>

<x>4</x>

<y>3.2</y>>

<z>11</z>

</numbers>

↓

A. 4 + 3.2 = 7.2

B. 3.2 - 4 = -0.8

C. 4 * 3.2 = 12.8

D. 11/3.2 = 3.4375

E. 4+3.2*11 = 39.2

F. (4+3.2)*11 = 79.2

G. 11 mod 4 = 3

H. 4 + 3.2 + 11 = 18.2

I. floor(3.2) = 3

J. ceiling(3.2) = 4

K. round(3.2) = 3

L. 11 + count(*) = 14

M. 3.2 + string-length("3.2") = 6.2

N. 11 + "hello" = NaN

<xsl:template match="numbers">

A. 4 + 3.2 = <xsl:value-of select="x + y"/>

B. 3.2 - 4 = <xsl:value-of select="y - x"/>

C. 4 * 3.2 = <xsl:value-of select="x * y"/>

D. 11/3.2 = <xsl:value-of select="z div y"/>

E. 4+3.2*11 = <xsl:value-of select="x+y*z"/>

F. (4+3.2)*11 = <xsl:value-of select="(x+y)*z"/>

G. 11 mod 4 = <xsl:value-of select="z mod x"/>

H. 4 + 3.2 + 11 = <xsl:value-of select="sum(*)"/>

I. floor(3.2) = <xsl:value-of select="floor(y)"/>

J. ceiling(3.2) = <xsl:value-of select="ceiling(y)"/>

K. round(3.2) = <xsl:value-of select="round(y)"/>

L. 11 + count(*) = <xsl:value-of select="11+count(*)"/>

M. 3.2 + string-length("3.2") = <xsl:value-of select="y + string-length(y)"/>

N. 11 + "hello" = <xsl:value-of select="z + 'hello'"/>

</xsl:template>

★ p.219 문자열 뽑아내기 함수들

<xsl:template match="verse">

1. By itself: {<xsl:value-of select="."/>}

2. {<xsl:value-of select="substring(.,7,6)"/>} <!-- 7번째 문자부터 6문자 -->

3. {<xsl:value-of select="substring(.,12)"/>}

4. {<xsl:value-of select="substring-before(.,'dreary')"/>}

5. {<xsl:value-of select="substring-after(.,'desolation')"/>}

</xsl:template>

★ p.220 그외 문자열 함수들

<xsl:template match="verse">

1. {<xsl:value-of select="concat('length: ', string-length(.))"/>}

2. {<xsl:if test="contains(.,'light')"><xsl:text>light: yes!</xsl:text></xsl:if>}

3. {<xsl:if test="starts-with(.,'Seest')">

<xsl:text>Yes, starts with "Seest"</xsl:text>

</xsl:if>}

4. {<xsl:value-of select="normalize-space(.)"/>}

5. {<xsl:value-of select="translate(.,'abcde','ABCDE')"/>}

</xsl:template>

normalize-space()는 주어진 문자열의 앞과 뒷부분에 있는 공백을 없애준다.

★ p.223 text() 사용하기

<xsl:template match="binCode">

<productLocation>

<row><xsl:value-of select="substring(text(), 1, 2)"/>

</row>

<shelf><xsl:value-of select="substring(.,3,1)"/>

</shelf>

<prodNum><xsl:value-of select="substring-after(text(), '-')'/>

</prodNum>

</productLocation>

</xsl:template>

여기서 text()와 .은 동일한 역할을 한다.
text()는 주어진 컨텍스트 노드의 자식 노드인 텍스트 노드를 가리키고, "."은 substring()의
첫번째 인자로 사용되었을 때 노드의 내용을 문자열로 표현한 것을 가리킨다.

★ p.225 두 문자열의 비교

<xsl:if test=". = 'full of Pomp and Gold'">

a = "full of Pomp and Gold"

</xsl:if>

<xsl:if test=". != ../c">

a != ../c

</xsl:if>

두 문자열의 같은지 다른지 여부는 = 와 != 를 이용한다.

★ p.228 문자열 치환 템플릿

<xsl:template name="globalReplace">

<xsl:param name="outputString"/>

<xsl:param name="target"/>

<xsl:param name="replacement"/>

<xsl:choose>

<xsl:when test="contains($outputString, $target)">

<xsl:value-of select="concat(substring-before($outputString, $target), $replacement)"/>

<xsl:call-template name="globalReplace">

<xsl:with-param name="outputString" select="substring-after($outputString, $target)"/>

<xsl:with-param name="target" select="$target"/>

<xsl:with-param name="replacement" select="$replacement"/>

</xsl:call-template>

</xsl:when>

<xsl:otherwise>

<xsl:value-of select="$outputString"/>

</xsl:otherwise>

</xsl:choose>

</xsl:template>

<xsl:template match="text()">

<xsl:call-template name="globalReplace">

<xsl:with-param name="outputString" select="."/>

<xsl:with-param name="target" select="'finish'"/>

<xsl:with-param name="replacement" select="'FINISH'"/>

</xsl:call-template>

</xsl:template>

<xsl:template match="@*|*">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

★ p.234 변수의 선언과 사용

<xsl:variable name="bodyTextSize">10pt</xsl:variable>

<xsl:template match="winery">

<b><font size="{$bodyTextSize}"><xsl:apply-template/>

<xsl:text> </xsl:text>

<xsl:value-of select="../@grape"/></font><b><br/>

</xsl:template>

<xsl:template match="product">

<i><font size="{$bodyTextSize}">

<xsl:apply-templates/></font></i><br/>

</xsl:template>

<xsl:template match="year | price">

<font size="{$bodyTextSize}"><xsl:apply-templates/></font><br/>

</xsl:template>

결과 트리에 반영되는 요소의 속성값이 변수나 매개변수가 가리키는 값을 넣으려고 할 때, 달러
기호가 붙은 변수가 그대로 찍히지 않게 하기 위해 위 예처럼 중괄호를 사용해야 한다. 속성이
아니라 요소의 내용에서 변수를 참조하기 위해서는 xsl:value-of 구문을 사용해야한다.

* 변수 선언시 select 를 이용하여 동적인 값을 줄 수 있다.

<xsl:variable name="baseFontSize" select="8"/>

<xsl:variable name="bodyTextSize" select="concat($baseFontSize+2, 'pt')" />

여기서 $bodyTextSize는 '10pt' 가 된다.

변수는 지역성을 갖는다. 동일한 이름을 갖더라도 선언 지역이 다르면 다른 변수이다.

★ p.237 변수를 사용하여 문자열을 오른쪽으로 정렬하기

<xsl:output omit-xml-declaration="yes"/>

<xsl:variable name="fieldWidth">12</xsl:variable> <!-- 12칸에 맞춰 오른쪽 정렬 -->

<xsl:template match="color">

<xsl:variable name="valueLength" select="string-length(.)"/>

<xsl:variable name="padding" select="$fieldWidth - $valueLength"/>

<xsl:value-of select="substring('            ',1,$padding)"/>

<xsl:value-of select="."/>

</xsl:template>

★ p.238 매개변수(parameter)
xsl:param 구문은 xsl:variable과 거의 같지만 한가지 차이점이 있다. 그 값은 단지 디폴트
값으로만 다루어지고, 런타임에서 재정의 될 수 있다.

<xsl:param name="bodyTextSize">10pt</xsl:param> <!-- 10pt는 런타임시 재 지정 될수 있다. -->

<xsl:template match="winery">

<b><font size="{$bodyTextSize}"><xsl:apply-templates/>

<xsl:text> </xsl:text>

<xsl:value-of select="../@grape"/></font></b><br/>

</xsl:template>

지역 매개변수는 p.228 문자열 치환 템플릿 참조

★ p.248 Key(키)에 의한 검색
(키,값)의 쌍으로 정보를 구성하여 키에 의해 값을 검색하는 구조

<shirts>

<colors>

<color cid="c1">yellow</color>

<color cid="c2">black</color>

<color cid="c3">red</color>

<color cid="c4">blue</color>

<color cid="c5">purple</color>

<color cid="c6">white</color>

<color cid="c7">orange</color>

<color cid="c7">green</color> <!-- 일부러 위와 동일하게 했슴 -->

</colors>

<shirt colorCode="c4">oxford button-down</shirt>

<shirt colorCode="c1">poly blend, straight collar</shirt>

<shirt colorCode="c6">monogrammed, tab collar</shirt>

</shirts>

↓

blue oxford button-down

yellow poly blend, straight collar

white monogrammed, tab collar

<color>의 @cid를 키로 이용해서 검색하면 <color>노드 자체가 리턴된다.
key 검색은 검색된 노드를 반환하는 것이지 문자열(text())을 반환하는 것이 아니다.

<xsl:key name="colorNumKey" match="color" use="@cid"/> <!-- 키 생성 -->

<xsl:template match="colors"/>

<xsl:template match="shirt">

<xsl:value-of select="key('colorNumKey', @colorCode)"/> <!-- key(키이름,키) -->

<xsl:text> </xsl:text><xsl:apply-templates/>

</xsl:template>

또 다른 방식으로 <color>의 text()를 키로 이용하여 <color>노드 얻기

Looking up the color name with the color ID:

c3's color: red

c4's color: blue

c8's color:

c7's color:

orange green

Looking up the color ID with the color name:

black's cid: c2

gray's cid:

위와 같은 결과를 얻으려면,

<xsl:output method="text"/>

<xsl:key name="colorNumKey" match="color" use="@cid"/>

<xsl:key name="colorKey" match="color" use="."/> <!-- color/text()를 키로 이용 -->

<xsl:variable name="testVar">c4</xsl:variable>

<xsl:variable name="keyName">colorKey</xsl:variable>

<xsl:template match="colors">

Looking up the color name with the color ID:

c3's color: <xsl:value-of select="key('colorNumKey', 'c3')"/>

c4's color: <xsl:value-of select="key('colorNumKey', $testVar)"/>

c8's color: <xsl:value-of select="key('colorNumKey', 'c8')"/> <!-- 존재하지 않는 키 -->

c7's color:

<xsl:for-each select="key('colorNumKey', 'c7')">

<xsl:value-of select="."/><xsl:text> </xsl:text>

</xsl:for-each>

Looking up the color ID with the color name:

black's cid: <xsl:value-of select="key($keyName, 'black')/@cid"/>

gray's cid: <xsl:value-of select="key('colorKey', 'gray')/@cid"/>

</xsl:template>

<xsl:template match="shirt"/>

★ p.253 마지막 figure 자식 노드의 마지막 title 요소의 값 얻기
<xsl:value-of select="descendant:figure/title[last()]"/>로는 원하는 결과를 얻을 수 없다.
이 문장은 각 figure 자식노드의 마지막 title 노드를 가져온다.

원하는 결과를 얻으려면,

<xsl:template match="chapter">

<xsl:for-each select="descendant::figure/title">

<xsl:if test="position() = 1"> <!-- 맨처음 figure/title만 가져옴 -->

First figure title in chapter: <xsl:value-of select="."/>

</xsl:if>

<xsl:if test="position() = last()"> <!-- 맨 마지막 figure/title만 가져옴 -->

Last figure title in chapter: <xsl:value-of select="."/>

</xsl:if>

</xsl:for-each>

</xsl:template>

★ p.254 알파벳 순으로 처음과 마지막 노드 얻기

<xsl:template match="chapter">

<xsl:for-each select="descendant::figure/title">

<xsl:sort/>

<xsl:if test="position() = 1"> <!-- 맨처음 figure/title만 가져옴 -->

First figure title in chapter: <xsl:value-of select="."/>

</xsl:if>

<xsl:if test="position() = last()"> <!-- 맨 마지막 figure/title만 가져옴 -->

Last figure title in chapter: <xsl:value-of select="."/>

</xsl:if>

</xsl:for-each>

</xsl:template>

★ p.255 자식 요소의 값에 따라 정렬한 뒤 맨 처음과 마지막 노드 얻기

<xsl:template match="employees">

<xsl:for-each select="employee">

<xsl:sort select="salary" data-type="number"/> <!-- 숫자로 간주하고 정렬하라. -->

<xsl:if test="position() = 1">

Lowest salary: <xsl:apply-templates/>

</xsl:if>

<xsl:if test="position() = last()">

Highest salary: <xsl:apply-templates/>

</xsl:if>

</xsl:for-each>

</xsl:template>

★ p.267 HTML 형식으로 출력
XSTL 형식으로 출력되는 결과물은 Text를 제외하고 well-formed 형식을 따라야 한다.
하지만 HTML은 well-formed 태그를 제대로 인식하지 못한다. 그의 해결책으로 XSLT의 xsl:output
요가 있다. 이 요소의 method 속성에 "html" 이라고 쓰면 XSLT 프로세서는 결과물을 만들때
XHTML형식으로 만들지 않고 HTML로 만든다. 그러마 XSLT 문서 작성시에는 well-formed로
만들어야 한다.

<xsl:output method="html"/>

★ p.270 XML 파일에 자신을 처리할 XSL 지정하기

<?xml version="1.0"?>

<?xml-stylesheet href="haha.xsl" "type="text/xsl"?>

<root>

등등...

모질라 1.4, IE 6.0 에서 모두 잘 보였슴.

★ p.274 한 XSLT문서로 여러 XML 문서 처리

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:template match="shirts">

<shirts>

<!-- 여기서 xq1.xml 을 읽어서 XSLT적용 -->

<xsl:apply-templates select="document('xq1.xml')"/>

<xsl:apply-templates/>

</shirts>

</xsl:template>

<xsl:tempalte match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

★ p.275 다른 XML문서의 일부 노드만 가져오기

<xsl:template match="shirts">

<shirts>

<!-- 속성 cid가 'c7'인것만 가저오라. -->

<xsl:apply-templates select="document('xq1.xml')//*[@cid='c7']"/>

<xsl:apply-templates/>

</shirts>

</xsl:template>

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

★ p.276 다른 XML문서를 가져와 Key로 이용하기

<!-- 다른 문서 삽입. 이 문서에 <color>노드가 있다. -->

<xsl:variable name="colorLookupDoc" select="document('xq1.xsl')"/>

<xsl:key name="colorNumKey" match="color" use="@cid"/>

<xsl:template match="shirts">

<xsl:apply-templates select="$colorLookupDoc"/>

<xsl:apply-templates/>

</xsl:template>

<xsl:template match="colors"/>

<xsl:template match="shirts">

<xsl:variable name="shirtColor" select="@colorCode"/>

<xsl:for-each select="$colorLookupdoc">

<xsl:value-of select="key('colorNumKey', $shirtColor)"/>

</xsl:for-each>

<xsl:text> </xsl:text><xsl:apply-templates/><xsl:txt>

</xsl:text>

</xsl:template>

★ p.279 mode를 이용해 한 노드집합에 두 개 이상의 템플릿 정의 - 차례와 목록 만들기

<xsl:template match="story">

<html>　　　　<body　　　　>

<h1>Table of Conetnts</h1>

<xsl:apply-templates select="chapter/title" mode="toc"/>

<xsl:apply-templates/></body></html>

</xsl:template>

<xsl:template match="chapter/title">

<h2><a name="{generate-id()}"/><xsl:apply-templates/></h2>

</xsl:template>

<xsl:template match="chapter/title" mode="toc">

<p><a href="#{generate-id()}"><xsl:apply-templates/></a></p>

</xsl:template>

<xsl:template match="para">

<p><xsl:apply-templates/></p>

</xsl:template>

<xsl:template match="story/title">

<h1><xsl:apply-templates/></h1>

</xsl:template>

★ 일반 Text 결과물 만들기

XSLT 프로세서로 하여금 결과 트레에 XML을 넣지 않도록 <xsl:output method="text">를 한다.

혹은 <xsl:output method="xml" omit-xml-decoration="yes">

text로 설정하면 <같은 것들이 자동으로 <로 변환된다.

★ p.286 번호 붙이기(Numbering)

<!-- 일반적인 방법. 항목 앞에 숫자와 점 공백 넣기 -->

<xsl:template match="color">

<xsl:number/>. <xsl:apply-templates/>

</xsl:template>

<!-- 숫자 형식 포맷팅 -->

<xsl:template match="colors">

<xsl:for-each select="color">

<xsl:number format="I. "/><xsl:value-of select="."/> <!-- I. II. III. 형식 -->

</xsl:for-each>

<xsl:for-each select="color">

<xsl:number format="i. "/><xsl:value-of selet="."/> <!-- i. ii. iii. 형식 -->

</xsl:for-each>

<xsl:for-each select="color">

<xsl:number format="A. "/><xsl:value-of select="."/> <!-- A. B. C. 형식 -->

</xsl:for-each>

<xsl:for-each select="color">

<xsl:number format="a. "/><xsl:value-of select="."/> <!-- a. b. c. 형식 -->

</xsl:for-each>

</xsl:template>

<xsl:template match="color">

<xsl:number format="001. "/><xsl:templates/> <!-- 001. 002. 003. 형식 -->

</xsl:template>

xsl:number에 grouping-separator 요소의 값으로 ","를 주고 grouping-size 요소에 3을 할당하면
999를 넘는 숫자에 대해서 세 자리마다 콤마를 찍어준다.

★ p.290 multiple 넘버링

<xsl:template match="color">

<xsl:number level="multiple" format="1. "/>

<xsl:apply-templates/>

</xsl:template>

다음과 같은 형식의 결과를 얻게된다.

1. red

2. green

3. blue

3.1 robin's egg

3.2 haha

4. yellow

★ p.293 여러 단계의 노드에 대해 multiple 넘버링

<xsl:template match="chapter">

<xsl:number format="1. "/>

<xsl:apply-templates/>

</xsl:template>

<xsl:template match="sect1">

<xsl:number format="1. " level="multiple" count="chapter|sect1"/>

<xsl:apply-templates/>

</xsl:template>

<xsl:template match="sect2">

<xsl:number format="1. " level="multiple" count="chapter|set1|sect2"/>

<xsl:apply-templates/>

</xsl:template>

다음과 같은 형식의 결과를 얻게된다.

1.

1.1

1.2

2.

2.1

2.1.1

2.1.2

2.2

★ p.294 노드의 깊이에 관계 없이 문서 전체에 걸쳐 순차적인 넘버링

<xsl:template match="figure">

<xsl:number format="1. " level="any"/><xsl:apply-templates/>

</xsl:template>

figure가 어느 노드의 자식이든지 간에 번호가 순서대로 먹여 진다.

★ p.295 노드의 깊이에 관계 없고, 특정 조상 태그마다 번호를 다시 시작하는 넘버링

<xsl:template match="figure">

<xsl:number format="1. " level="any" from="chapter"/>

<xsl:apply-templates/>

</xsl:template>

xsl:number 요소를 자주 사용하면 XSLT 프로세서의 속도가 떨어진다.
되도록 position()을 사용하라.

<xsl:template match="colors">

<xsl:for-each select="color">

<xsl:value-of select="position()"/>. <xsl:value-of select="."/>

<xsl:text>

</xsl:text>

</xsl:for-each>

</xsl:template>

여기서 꼭 xsl:for-each를 써야한다. 그냥 xsl:template 을 사용하면 안된다. XSLT 프로세서는
colors 요소들의 자식 요소들 중에 각 color 요소들 사이의 개행문자를 포함하고 있는 텍스트
노드까지 포함하여 각 color 요소의 위치를 계산한다.

★ p.301 숫자에 의한 정렬 / 역순 정렬

<xsl:template match="employees">

<xsl:apply-templates>

<xsl:sort select="salary" data-type="number" order="descending"/>

</xsl:apply-templates>

</xsl:template>

★ p.301 다중 정렬

<xsl:template match="employees">

<xsl:apply-templates>

<xsl:sort select="last"/> <!-- last/first는 요소의 이름임 -->

<xsl:sort select="first"/>

</xsl:apply-templates>

</xsl:template>

★ p.303 속성에 의한 정렬(날짜 순)

<xsl:template match="employees">

<xsl:apply-templates>

<!-- hireDate는 04/23/1999 형심임 -->

<xsl:sort select="substring(@hireDate, 7, 4)"/> <!-- year -->

<xsl:sort select="substring(@hireDate, 1, 2)"/> <!-- month -->

<xsl:sort select="substring(@hireDate, 3, 2)"/> <!-- day -->

</xsl:apply-templates>

</xsl:template>

★ p.305 손자 요소에 의한 정렬

<xsl:template match="winelist">

<xsl:copy>

<xsl:apply-templates>

<xsl:sort data-type="number" select="prices/discounted"/> <!-- 손자 요소를

조거으로 -->

</xsl:templates>

</xsl:copy>

</xsl:template>

<xsl:template match="*"

<xsl:copy>

<xsl:apply-templates/>

</xsl:copy>

</xsl:template>

xsl:sort는 xsl:for-each와 함께 쓸때 강력해진다.

★ p.313 XML문서 생성하며 Doctype 삽입

<xsl:output method="xml" doctype-system="../dtds/docbookx.dtd"

doctype-public="-//OASIS//DTD DocBook XML//EN"/>

<xsl:template match="@*|node()">

어쩌구...

아래 문구가 삽입된다.
아래에서 chapter는 생성될 xml 문서의 root 요소이다.

<!DOCTYPE chapter

PUBLIC "-//OASIS//DTD DocBook XML/EN" "../dtds/docbookx.dtd">

[ ] 안에 DTD 선언을 넣을 수는 없다. System 속성에 있는 외부 DTD에 모든 선언을 넣어야 한다.

★ p.315 XML 선언 넣기

<xsl:output method="xml" version="1.0" encoding="utf-8"/>

위 선언에 의해 생성된 xml 파일은 다음으로 시작된다.

<?xml version="1.0" encoding="utf-8"?>

★ p.316 XML 선언 빼기
자동으로 들어가는 선언을 빼려면..

<xsl:output method="xml" omit-xml-declaration="yes"/>

★ p.318 특정 요소가 갖고 있는 불필요한 공백을 문서 전체에 걸쳐 제거

<xsl:strip-space elements="color"/>

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

위의 스타일 시트는 원본 XML에서 color 요소의 공백을 제거하고 모든 내용을 그대로
복사한다.

★ p.320 공백 그냥 놔두기

<xsl:strip-space elements="*"/> <!-- 모든 요소의 공백을 제거하라 -->

<!-- codeListing과 sampleOutput만 빼고 -->

<xsl:preserve-space elements="codeListing sampleOutput"/>

★ p.321 들여쓰기(indentation) : xml 문서를 적당히 들여쓰기 한다.

<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

indent="yes"에 의해 들여쓰기가 된다.

★ p.326 공백과 개행문자, Tab문자 처리
공백과 개행문자를 엔티티로 선언하면 사용하기 쉽다.

<!DOCTYPE stylesheet [

ENTITY space "<xsl:text> </xsl:text>"

ENTITY cr "<xsl:text>

</xsl:text>"

ENTITY tab "<xsl:text>	</xsl:text>"

]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:template match="employee">

<xsl:apply-templates select="@hireDate"/>&cr;

<xsl:apply-templates select="first"/>&space;&tab; <!-- 공백과 탭 삽입 -->

<xsl:apply-templates select="last"/>

</xsl:template>

</xsl:stylesheet>

XML 프로세서는 요소 안에 다른 문자 데이터와 함께 개행 문자가 들어가 있으면 이를 제거하지
않는다. 일반 문자열에서 개행 문자가 작동하지 않게 하려면 <xsl:text>를 이용한다.

<xsl:text>Date</xsl:text>

★ p.334 유일한 ID 생성

<xsl:template match="chapter | sect1 | sect2">

<xsl:copy>

<xsl:attribute name="uid">

<xsl:value-of select="generate-id(.)"/> <!-- ID 생성 -->

</xsl:attribute>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

★ p.336 generate-id()를 이용한 문서내 자동 링크 생성

<xsl:output method="html"/>

<xsl:template match="chapter">

<html>　　　　<body　　　　>

<!-- Generate a list of picture titles, with each title linking to the picture in the

poem below -->

<b>Pictures:</b><br/>

<xsl:for-each select="descendant::figure">

<a href="#{generate-id(graphic)}">

<xsl:value-of select="title"/></a><br/>

</xsl:for-each>

<xsl:apply-templates/>

</body></html>

</xsl:template>

<xsl:template match="para">

<p><xsl:apply-templates/></p>

</xsl:template>

<xsl:template match="graphic">

<!-- 위에 각 graphic 요소마다 생성된 id와 동일한 id가 생성된다. -->

<center><a name="{generate-id(.)}"><img src=http://img.yahoo.co.kr/blank.gif></a>

<b><xsl:value-of select="../title"/></b></center>

</xsl:template>

<xsl:template match="figure/title"/>

</xsl:stylesheet>

★ 문서 전체를 그대로 복사하며 불필요한 노드 삭제하기

<!-- 아래는 문서 전체를 그대로 복사한다 -->

<xsl:template match="@*|node()">

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:template>

<!-- 아래에 의해 불필요한 노드가 삭제된다. -->

<xsl:template match="불필요한 노드"/>