์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ—‚๏ธ XML ยท XSLT ยท XPath๋ฅผ ํ™œ์šฉํ•œ ๊ตฌ์กฐํ™”๋œ ๋ฌธ์„œ ์ฒ˜๋ฆฌ์™€ ๋ณ€ํ™˜ ๊ธฐ์ˆ 
ํ”„๋กœ๊ทธ๋žจ๊ฐœ๋ฐœ ยท ๊ธฐํƒ€ํ”„๋กœ๊ทธ๋žจ๊ฐœ๋ฐœ

๐Ÿ—‚๏ธ XML ยท XSLT ยท XPath๋ฅผ ํ™œ์šฉํ•œ ๊ตฌ์กฐํ™”๋œ ๋ฌธ์„œ ์ฒ˜๋ฆฌ์™€ ๋ณ€ํ™˜ ๊ธฐ์ˆ 

๋ฐ์ดํ„ฐ๋ฅผ ์ž์œ ์ž์žฌ๋กœ ์š”๋ฆฌํ•˜๋Š” XML ํŠธ๋ฆฌ์˜ค์˜ ์„ธ๊ณ„๋กœ ํ•จ๊ป˜ ๋– ๋‚˜๋ณด์ž! ๐Ÿš€

XML ํŠธ๋ฆฌ์˜ค์˜ ํ˜‘์—… ๊ตฌ์กฐ ๐Ÿ“„ XML ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ โš™๏ธ XSLT ๋ณ€ํ™˜ ๊ทœ์น™ ์ •์˜ ๐Ÿ” XPath ๋…ธ๋“œ ํƒ์ƒ‰ ๋ฐ ์„ ํƒ ์ž…๋ ฅ ๋…ธ๋“œ ์„ ํƒ ์ง€์› ๐ŸŽฏ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ HTML ยท PDF ยท ํ…์ŠคํŠธ ยท ๋‹ค๋ฅธ XML ๋“ฑ
๐Ÿค” XML์ด ๋ญ”๋ฐ? ์™œ ์ด๊ฑธ ๋ฐฐ์›Œ์•ผ ํ•ด?

์†”์งํžˆ ๋งํ•˜๋ฉด, ์ฒ˜์Œ XML์ด๋ผ๋Š” ๋‹จ์–ด๋ฅผ ๋“ค์—ˆ์„ ๋•Œ "๋˜ ๋ญ” ์•ฝ์ž์•ผ..." ์‹ถ์—ˆ๋˜ ์‚ฌ๋žŒ ์†! โœ‹
๊ทผ๋ฐ ์•Œ๊ณ  ๋ณด๋ฉด XML์€ ์šฐ๋ฆฌ ์ผ์ƒ ๊ณณ๊ณณ์— ์ˆจ์–ด์žˆ๋Š” ์—„์ฒญ๋‚œ ์นœ๊ตฌ์•ผ.
์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ ์„ค์ • ํŒŒ์ผ, ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ ์˜คํ”ผ์Šค ๋ฌธ์„œ(.docx, .xlsx), RSS ํ”ผ๋“œ, ์›น ์„œ๋น„์Šค API ์‘๋‹ต๊ฐ’...
์ „๋ถ€ XML ๊ธฐ๋ฐ˜์ด๊ฑฐ๋‚˜ XML์—์„œ ํŒŒ์ƒ๋œ ํ˜•์‹์ด๊ฑฐ๋“ . ๐Ÿ˜ฒ

XML(eXtensible Markup Language)์€ 1998๋…„ W3C์—์„œ ํ‘œ์ค€ํ™”ํ•œ ๋งˆํฌ์—… ์–ธ์–ด์•ผ.
HTML์ด "์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ค„๊นŒ"์— ์ง‘์ค‘ํ•œ๋‹ค๋ฉด, XML์€ "๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌ์กฐํ™”ํ• ๊นŒ"์— ์ง‘์ค‘ํ•ด.
ํƒœ๊ทธ๋ฅผ ๋งˆ์Œ๋Œ€๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์„œ "ํ™•์žฅ ๊ฐ€๋Šฅํ•œ(eXtensible)" ๋งˆํฌ์—… ์–ธ์–ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๊ฑฐ์ง€.

๐Ÿ“Œ XML์˜ ํ•ต์‹ฌ ํŠน์ง•
ํŠน์ง•์„ค๋ช…
์ž๊ธฐ ์„œ์ˆ ์ (Self-describing)ํƒœ๊ทธ ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ๋ฐ์ดํ„ฐ์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•จ
ํ”Œ๋žซํผ ๋…๋ฆฝ์ OS, ์–ธ์–ด, ์‹œ์Šคํ…œ์— ์ƒ๊ด€์—†์ด ๋ฐ์ดํ„ฐ ๊ตํ™˜ ๊ฐ€๋Šฅ
๊ณ„์ธต ๊ตฌ์กฐ(Tree Structure)๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘์ฒฉ ํ‘œํ˜„
์œ ๋‹ˆ์ฝ”๋“œ ์ง€์›ํ•œ๊ธ€, ์ผ๋ณธ์–ด, ์•„๋ž์–ด ๋“ฑ ๋‹ค๊ตญ์–ด ์™„๋ฒฝ ์ง€์›
ํ™•์žฅ์„ฑ์‚ฌ์šฉ์ž ์ •์˜ ํƒœ๊ทธ๋กœ ์–ด๋–ค ๋„๋ฉ”์ธ์—๋„ ์ ์šฉ ๊ฐ€๋Šฅ

๐Ÿ“„ XML ๋ฌธ์„œ ๊ตฌ์กฐ ํŒŒํ—ค์น˜๊ธฐ

XML ๋ฌธ์„œ๋Š” ํฌ๊ฒŒ ํ”„๋กค๋กœ๊ทธ(Prolog)์™€ ๋ฌธ์„œ ์š”์†Œ(Document Element)๋กœ ๋‚˜๋‰˜์–ด.
์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด์„œ ์ดํ•ดํ•ด๋ณด์ž!

<?xml version="1.0" encoding="UTF-8"?>
<!-- ์ด๊ฑด XML ์„ ์–ธ๋ถ€ (ํ”„๋กค๋กœ๊ทธ) -->

<๋„์„œ๋ชฉ๋ก>
  <๋„์„œ id="001" ์นดํ…Œ๊ณ ๋ฆฌ="ํ”„๋กœ๊ทธ๋ž˜๋ฐ">
    <์ œ๋ชฉ>XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ</์ œ๋ชฉ>
    <์ €์ž>ํ™๊ธธ๋™</์ €์ž>
    <์ถœํŒ๋…„๋„>2024</์ถœํŒ๋…„๋„>
    <๊ฐ€๊ฒฉ ํ†ตํ™”="KRW">28000</๊ฐ€๊ฒฉ>
  </๋„์„œ>
  <๋„์„œ id="002" ์นดํ…Œ๊ณ ๋ฆฌ="์›น๊ฐœ๋ฐœ">
    <์ œ๋ชฉ>XSLT ์‹ค์ „ ๊ฐ€์ด๋“œ</์ œ๋ชฉ>
    <์ €์ž>๊น€์ฒ ์ˆ˜</์ €์ž>
    <์ถœํŒ๋…„๋„>2023</์ถœํŒ๋…„๋„>
    <๊ฐ€๊ฒฉ ํ†ตํ™”="KRW">32000</๊ฐ€๊ฒฉ>
  </๋„์„œ>
</๋„์„œ๋ชฉ๋ก>

์œ„ ์ฝ”๋“œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, XML์€ ํƒœ๊ทธ(Tag), ์†์„ฑ(Attribute), ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋กœ ๊ตฌ์„ฑ๋ผ.
๊ทธ๋ฆฌ๊ณ  ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์˜ ๋ฃจํŠธ ์š”์†Œ(<๋„์„œ๋ชฉ๋ก>)๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๋ชจ๋“  ํƒœ๊ทธ๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ซํ˜€์•ผ ํ•ด.

๐Ÿ’ก Well-formed vs Valid XML
Well-formed(ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅธ): XML ๋ฌธ๋ฒ• ๊ทœ์น™์„ ์ง€ํ‚จ ๋ฌธ์„œ (ํƒœ๊ทธ ๋‹ซ๊ธฐ, ๋Œ€์†Œ๋ฌธ์ž ์ผ์น˜ ๋“ฑ)
Valid(์œ ํšจํ•œ): DTD๋‚˜ XML Schema์— ๋”ฐ๋ผ ๊ตฌ์กฐ๊นŒ์ง€ ๊ฒ€์ฆ๋œ ๋ฌธ์„œ
Well-formed๋Š” ํ•„์ˆ˜, Valid๋Š” ์„ ํƒ์ด์ง€๋งŒ ์—„๊ฒฉํ•œ ๋ฐ์ดํ„ฐ ๊ตํ™˜ ์‹œ์—” Valid๋„ ์ค‘์š”ํ•ด!
๐ŸŒณ XML ๋…ธ๋“œ์˜ ์ข…๋ฅ˜

XML ๋ฌธ์„œ๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ๋…ธ๋“œ๋กœ ๊ตฌ์„ฑ๋œ ํŠธ๋ฆฌ์•ผ. ๊ฐ ๋…ธ๋“œ ํƒ€์ž…์„ ์•Œ์•„์•ผ XPath๋ฅผ ์ œ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ์–ด!

๐Ÿ“ฆ ์š”์†Œ ๋…ธ๋“œ
<์ œ๋ชฉ>...</์ œ๋ชฉ>
๊ฐ€์žฅ ๊ธฐ๋ณธ ๋‹จ์œ„
๐Ÿท๏ธ ์†์„ฑ ๋…ธ๋“œ
id="001"
์š”์†Œ์˜ ๋ฉ”ํƒ€์ •๋ณด
๐Ÿ“ ํ…์ŠคํŠธ ๋…ธ๋“œ
ํƒœ๊ทธ ์‚ฌ์ด์˜
์‹ค์ œ ํ…์ŠคํŠธ ๊ฐ’
๐Ÿ’ฌ ์ฃผ์„ ๋…ธ๋“œ
<!-- ์ฃผ์„ -->
์ฒ˜๋ฆฌ์— ๋ฌด์‹œ๋จ

๐Ÿ” XPath: XML ๋ฌธ์„œ์˜ GPS ๋‚ด๋น„๊ฒŒ์ด์…˜

XPath(XML Path Language)๋Š” XML ๋ฌธ์„œ ๋‚ด์—์„œ ์›ํ•˜๋Š” ๋…ธ๋“œ๋ฅผ ์ฐพ์•„๊ฐ€๋Š” ๊ฒฝ๋กœ ํ‘œํ˜„ ์–ธ์–ด์•ผ.
๋งˆ์น˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๊ฒฝ๋กœ์ฒ˜๋Ÿผ "/" ์Šฌ๋ž˜์‹œ๋กœ ๊ณ„์ธต์„ ํ‘œํ˜„ํ•˜๋Š”๋ฐ, ํ›จ์”ฌ ๊ฐ•๋ ฅํ•œ ํ•„ํ„ฐ๋ง ๊ธฐ๋Šฅ๊นŒ์ง€ ๊ฐ–์ถ”๊ณ  ์žˆ์–ด.
XPath๋Š” XSLT์˜ ํ•ต์‹ฌ ์—”์ง„์ด๊ธฐ๋„ ํ•˜๊ณ , ์›น ์Šคํฌ๋ž˜ํ•‘, ํ…Œ์ŠคํŠธ ์ž๋™ํ™”(Selenium) ๋“ฑ์—๋„ ๋„๋ฆฌ ์“ฐ์—ฌ. ๐Ÿ—บ๏ธ

๐Ÿ“ XPath ๊ธฐ๋ณธ ๋ฌธ๋ฒ• - ๊ฒฝ๋กœ ํ‘œํ˜„์‹
/* ์ ˆ๋Œ€ ๊ฒฝ๋กœ (๋ฃจํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘) */
/๋„์„œ๋ชฉ๋ก/๋„์„œ/์ œ๋ชฉ

/* ์ƒ๋Œ€ ๊ฒฝ๋กœ (ํ˜„์žฌ ์ปจํ…์ŠคํŠธ ๊ธฐ์ค€) */
๋„์„œ/์ œ๋ชฉ

/* ์–ด๋””์„œ๋“  ์ฐพ๊ธฐ (ํ•˜์œ„ ์ „์ฒด ํƒ์ƒ‰) */
//์ œ๋ชฉ

/* ํŠน์ • ์†์„ฑ์œผ๋กœ ํ•„ํ„ฐ๋ง */
//๋„์„œ[@id='001']

/* ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ 'ํ”„๋กœ๊ทธ๋ž˜๋ฐ'์ธ ๋„์„œ์˜ ์ œ๋ชฉ */
//๋„์„œ[@์นดํ…Œ๊ณ ๋ฆฌ='ํ”„๋กœ๊ทธ๋ž˜๋ฐ']/์ œ๋ชฉ

/* ์ฒซ ๋ฒˆ์งธ ๋„์„œ */
/๋„์„œ๋ชฉ๋ก/๋„์„œ[1]

/* ๋งˆ์ง€๋ง‰ ๋„์„œ */
/๋„์„œ๋ชฉ๋ก/๋„์„œ[last()]

/* ๊ฐ€๊ฒฉ์ด 30000 ์ด์ƒ์ธ ๋„์„œ */
//๋„์„œ[๊ฐ€๊ฒฉ >= 30000]
โšก XPath ์ถ•(Axis) - ๋ฐฉํ–ฅ์„ ์ •ํ•˜๋Š” ๋‚˜์นจ๋ฐ˜

XPath์˜ ์ง„์งœ ๊ฐ•๋ ฅํ•จ์€ ์ถ•(Axis)์— ์žˆ์–ด.
ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์–ด๋А ๋ฐฉํ–ฅ์œผ๋กœ ํƒ์ƒ‰ํ• ์ง€ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ !

์ถ• ์ด๋ฆ„์˜๋ฏธ์˜ˆ์‹œ
child::์ž์‹ ๋…ธ๋“œchild::๋„์„œ
parent::๋ถ€๋ชจ ๋…ธ๋“œparent::๋„์„œ๋ชฉ๋ก
ancestor::๋ชจ๋“  ์กฐ์ƒ ๋…ธ๋“œancestor::๋„์„œ๋ชฉ๋ก
descendant::๋ชจ๋“  ์ž์† ๋…ธ๋“œdescendant::์ œ๋ชฉ
following-sibling::๋‹ค์Œ ํ˜•์ œ ๋…ธ๋“œ๋“คfollowing-sibling::๋„์„œ
preceding-sibling::์ด์ „ ํ˜•์ œ ๋…ธ๋“œ๋“คpreceding-sibling::๋„์„œ
attribute::์†์„ฑ ๋…ธ๋“œattribute::id
self::ํ˜„์žฌ ๋…ธ๋“œ ์ž์‹ self::๋„์„œ
๐Ÿงฎ XPath ํ•จ์ˆ˜๋“ค - ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต์˜ ๋„๊ตฌ๋“ค

XPath๋Š” ๋‹จ์ˆœ ํƒ์ƒ‰์„ ๋„˜์–ด ๋‹ค์–‘ํ•œ ๋‚ด์žฅ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•ด. ์ž์ฃผ ์“ฐ๋Š” ๊ฒƒ๋“ค๋งŒ ์ •๋ฆฌํ•ด๋ณผ๊ฒŒ!

/* ๋ฌธ์ž์—ด ํ•จ์ˆ˜ */
string(๋…ธ๋“œ)           /* ๋…ธ๋“œ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ */
concat('Hello', ' ', 'World')  /* ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ */
substring('ํ”„๋กœ๊ทธ๋ž˜๋ฐ', 1, 3)   /* ๋ถ€๋ถ„ ๋ฌธ์ž์—ด */
contains(์ œ๋ชฉ, 'XML')           /* ํฌํ•จ ์—ฌ๋ถ€ ํ™•์ธ */
starts-with(์ œ๋ชฉ, 'XML')        /* ์‹œ์ž‘ ๋ฌธ์ž์—ด ํ™•์ธ */
string-length(์ œ๋ชฉ)             /* ๋ฌธ์ž์—ด ๊ธธ์ด */
normalize-space(์ œ๋ชฉ)           /* ์•ž๋’ค ๊ณต๋ฐฑ ์ œ๊ฑฐ */
translate(์ œ๋ชฉ, 'abc', 'ABC')   /* ๋ฌธ์ž ์น˜ํ™˜ */

/* ์ˆซ์ž ํ•จ์ˆ˜ */
count(//๋„์„œ)          /* ๋…ธ๋“œ ๊ฐœ์ˆ˜ */
sum(//๊ฐ€๊ฒฉ)            /* ํ•ฉ๊ณ„ */
round(3.7)             /* ๋ฐ˜์˜ฌ๋ฆผ โ†’ 4 */
floor(3.7)             /* ๋‚ด๋ฆผ โ†’ 3 */
ceiling(3.2)           /* ์˜ฌ๋ฆผ โ†’ 4 */

/* ๋ถˆ๋ฆฌ์–ธ ํ•จ์ˆ˜ */
not(@id)               /* ์†์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ */
true()                 /* ํ•ญ์ƒ ์ฐธ */
false()                /* ํ•ญ์ƒ ๊ฑฐ์ง“ */

/* ๋…ธ๋“œ ์ง‘ํ•ฉ ํ•จ์ˆ˜ */
position()             /* ํ˜„์žฌ ์œ„์น˜ ๋ฒˆํ˜ธ */
last()                 /* ๋งˆ์ง€๋ง‰ ์œ„์น˜ ๋ฒˆํ˜ธ */
name()                 /* ๋…ธ๋“œ ์ด๋ฆ„ */
local-name()           /* ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ œ์™ธ ์ด๋ฆ„ */
๐Ÿ’ก XPath 2.0 vs 1.0
XPath 1.0์€ XSLT 1.0๊ณผ ํ•จ๊ป˜ ์“ฐ์ด๋Š” ๊ธฐ๋ณธ ๋ฒ„์ „์ด๊ณ ,
XPath 2.0์€ XSLT 2.0์—์„œ ์ง€์›ํ•˜๋ฉฐ ์ •๊ทœํ‘œํ˜„์‹, ์‹œํ€€์Šค, ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์‹œ์Šคํ…œ์ด ์ถ”๊ฐ€๋์–ด.
ํ˜„์—…์—์„œ๋Š” ์•„์ง 1.0๋„ ๋งŽ์ด ์“ฐ์ด๋‹ˆ ๋‘˜ ๋‹ค ์•Œ์•„๋‘๋ฉด ์ข‹์•„!
๐ŸŒณ XML ํŠธ๋ฆฌ ๊ตฌ์กฐ์™€ XPath ํƒ์ƒ‰ ๊ฒฝ๋กœ ๋„์„œ๋ชฉ๋ก (๋ฃจํŠธ) ๋„์„œ id="001" ๋„์„œ id="002" ์ œ๋ชฉ ์ €์ž ๊ฐ€๊ฒฉ ์ œ๋ชฉ ์ €์ž ๊ฐ€๊ฒฉ XPath ์˜ˆ์‹œ: //๋„์„œ[@id='001']/์ œ๋ชฉ โ†’ "XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ" ํ…์ŠคํŠธ ๋…ธ๋“œ ์„ ํƒ

โš™๏ธ XSLT: XML์„ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€์‹ ์‹œํ‚ค๋Š” ๋งˆ๋ฒ•์‚ฌ

์ž, ์ด์ œ ์ง„์งœ ๊ฝƒ์ธ XSLT(eXtensible Stylesheet Language Transformations)๋ฅผ ์•Œ์•„๋ณผ ์ฐจ๋ก€์•ผ! ๐ŸŽฉโœจ
XSLT๋Š” XML ๋ฌธ์„œ๋ฅผ ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์–ธ์–ด์ธ๋ฐ, ์žฌ๋ฐŒ๋Š” ๊ฑด XSLT ์ž์ฒด๋„ XML ๋ฌธ์„œ๋ผ๋Š” ๊ฑฐ์•ผ.
์ฆ‰, XML๋กœ XML์„ ๋ณ€ํ™˜ํ•˜๋Š” ๊ทœ์น™์„ ์ž‘์„ฑํ•˜๋Š” ์…ˆ์ด์ง€. ๋ฉ”ํƒ€์ ์ด์ง€ ์•Š์•„? ๐Ÿ˜„

XSLT ํ”„๋กœ์„ธ์„œ(Saxon, Xalan, libxslt ๋“ฑ)๊ฐ€ XML ์†Œ์Šค ๋ฌธ์„œ์™€ XSLT ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ๋ฐ›์•„์„œ
HTML, ํ…์ŠคํŠธ, ๋‹ค๋ฅธ XML, PDF(FO๋ฅผ ํ†ตํ•ด) ๋“ฑ ๋‹ค์–‘ํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด๋‚ด.

๐Ÿ—๏ธ XSLT ๋ฌธ์„œ์˜ ๊ธฐ๋ณธ ๊ณจ๊ฒฉ
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- ์ถœ๋ ฅ ํ˜•์‹ ์ง€์ • -->
  <xsl:output method="html" encoding="UTF-8" indent="yes"/>

  <!-- ๋ฃจํŠธ ํ…œํ”Œ๋ฆฟ -->
  <xsl:template match="/">
    <html>
      <body>
        <h1>๋„์„œ ๋ชฉ๋ก</h1>
        <xsl:apply-templates select="๋„์„œ๋ชฉ๋ก/๋„์„œ"/>
      </body>
    </html>
  </xsl:template>

  <!-- ๋„์„œ ์š”์†Œ ์ฒ˜๋ฆฌ ํ…œํ”Œ๋ฆฟ -->
  <xsl:template match="๋„์„œ">
    <div>
      <h2><xsl:value-of select="์ œ๋ชฉ"/></h2>
      <p>์ €์ž: <xsl:value-of select="์ €์ž"/></p>
      <p>๊ฐ€๊ฒฉ: <xsl:value-of select="๊ฐ€๊ฒฉ"/>์›</p>
    </div>
  </xsl:template>

</xsl:stylesheet>
๐ŸŽฏ ํ•ต์‹ฌ XSLT ์š”์†Œ๋“ค ์™„์ „ ์ •๋ฆฌ
โ‘  xsl:template - ๋ณ€ํ™˜ ๊ทœ์น™์˜ ๊ธฐ๋ณธ ๋‹จ์œ„
match ์†์„ฑ์— XPath๋ฅผ ์จ์„œ ์–ด๋–ค ๋…ธ๋“œ์— ์ ์šฉํ• ์ง€ ์ง€์ •ํ•ด.
name ์†์„ฑ์œผ๋กœ ์ด๋ฆ„์„ ๋ถ™์ด๋ฉด xsl:call-template๋กœ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์“ธ ์ˆ˜ ์žˆ์–ด.
<!-- match๋กœ ํŒจํ„ด ๋งค์นญ -->
<xsl:template match="๋„์„œ[@์นดํ…Œ๊ณ ๋ฆฌ='ํ”„๋กœ๊ทธ๋ž˜๋ฐ']">
  <span style="color:blue">
    <xsl:value-of select="์ œ๋ชฉ"/>
  </span>
</xsl:template>

<!-- name์œผ๋กœ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ…œํ”Œ๋ฆฟ -->
<xsl:template name="๊ฐ€๊ฒฉํฌ๋งท">
  <xsl:param name="๊ธˆ์•ก"/>
  <xsl:value-of select="format-number($๊ธˆ์•ก, '#,###')"/>์›
</xsl:template>
โ‘ก xsl:for-each - ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ์˜ ํ•ต์‹ฌ
์„ ํƒ๋œ ๋…ธ๋“œ ์ง‘ํ•ฉ์„ ์ˆœํšŒํ•˜๋ฉด์„œ ๋™์ผํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋ฐ˜๋ณตํ•ด. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ for ๋ฃจํ”„์™€ ๋น„์Šทํ•ด!
<xsl:for-each select="๋„์„œ๋ชฉ๋ก/๋„์„œ">
  <!-- ์ •๋ ฌ๋„ ๊ฐ€๋Šฅ! -->
  <xsl:sort select="๊ฐ€๊ฒฉ" data-type="number" order="ascending"/>
  <tr>
    <td><xsl:value-of select="position()"/></td>
    <td><xsl:value-of select="์ œ๋ชฉ"/></td>
    <td><xsl:value-of select="๊ฐ€๊ฒฉ"/></td>
  </tr>
</xsl:for-each>
โ‘ข xsl:if / xsl:choose - ์กฐ๊ฑด ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ
ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ if-else, switch-case์™€ ๊ฐ™์€ ์—ญํ• ์ด์•ผ!
<!-- ๋‹จ์ˆœ ์กฐ๊ฑด -->
<xsl:if test="๊ฐ€๊ฒฉ > 30000">
  <span class="expensive">๊ณ ๊ฐ€ ๋„์„œ</span>
</xsl:if>

<!-- ๋‹ค์ค‘ ์กฐ๊ฑด (if-else if-else) -->
<xsl:choose>
  <xsl:when test="๊ฐ€๊ฒฉ < 20000">
    <span style="color:green">์ €๋ ด</span>
  </xsl:when>
  <xsl:when test="๊ฐ€๊ฒฉ < 35000">
    <span style="color:orange">๋ณดํ†ต</span>
  </xsl:when>
  <xsl:otherwise>
    <span style="color:red">๊ณ ๊ฐ€</span>
  </xsl:otherwise>
</xsl:choose>
โ‘ฃ xsl:variable / xsl:param - ๋ณ€์ˆ˜์™€ ํŒŒ๋ผ๋ฏธํ„ฐ
XSLT์—์„œ ๋ณ€์ˆ˜๋Š” ํ•œ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€(๋ถˆ๋ณ€)์•ผ. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋А๋‚Œ!
<!-- ๋ณ€์ˆ˜ ์„ ์–ธ -->
<xsl:variable name="์ด๋„์„œ์ˆ˜" select="count(//๋„์„œ)"/>
<xsl:variable name="ํ‰๊ท ๊ฐ€๊ฒฉ" select="sum(//๊ฐ€๊ฒฉ) div $์ด๋„์„œ์ˆ˜"/>

<p>์ด <xsl:value-of select="$์ด๋„์„œ์ˆ˜"/>๊ถŒ,
   ํ‰๊ท ๊ฐ€๊ฒฉ: <xsl:value-of select="format-number($ํ‰๊ท ๊ฐ€๊ฒฉ, '#,###')"/>์›
</p>

<!-- ํŒŒ๋ผ๋ฏธํ„ฐ (์™ธ๋ถ€์—์„œ ๊ฐ’ ์ „๋‹ฌ ๊ฐ€๋Šฅ) -->
<xsl:param name="์„ ํƒ์นดํ…Œ๊ณ ๋ฆฌ" select="'์ „์ฒด'"/>
๐Ÿ”„ xsl:apply-templates vs xsl:call-template

์ด ๋‘˜์˜ ์ฐจ์ด๋ฅผ ํ—ท๊ฐˆ๋ คํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋งŽ์€๋ฐ, ๋ช…ํ™•ํ•˜๊ฒŒ ์ •๋ฆฌํ•ด์ค„๊ฒŒ!

๊ตฌ๋ถ„xsl:apply-templatesxsl:call-template
๋™์ž‘ ๋ฐฉ์‹ํŒจํ„ด ๋งค์นญ์œผ๋กœ ์ž๋™ ์„ ํƒ์ด๋ฆ„์œผ๋กœ ์ง์ ‘ ํ˜ธ์ถœ
์ปจํ…์ŠคํŠธ ๋ณ€๊ฒฝ์„ ํƒ๋œ ๋…ธ๋“œ๋กœ ๋ณ€๊ฒฝ๋จํ˜„์žฌ ์ปจํ…์ŠคํŠธ ์œ ์ง€
๋น„์œ ๋‹คํ˜•์„ฑ(Polymorphism)ํ•จ์ˆ˜ ํ˜ธ์ถœ
์‚ฌ์šฉ ์‹œ์ ๋…ธ๋“œ ํƒ€์ž…๋ณ„ ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋กœ์ง

๐Ÿš€ ์‹ค์ „ ์˜ˆ์ œ: XML โ†’ HTML ๋ณ€ํ™˜ ์™„์ „ ๊ตฌํ˜„

์ด์ œ ์ด๋ก ์€ ์ถฉ๋ถ„ํžˆ ๋ดค์œผ๋‹ˆ, ์‹ค์ œ๋กœ ๋™์ž‘ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋งŒ๋“ค์–ด๋ณด์ž!
๋„์„œ ๋ชฉ๋ก XML์„ ์˜ˆ์œ HTML ํ…Œ์ด๋ธ”๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์™„์ „ํ•œ ์˜ˆ์ œ์•ผ. ๐Ÿ’ช

๐Ÿ“„ ์†Œ์Šค XML (books.xml)
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="books.xsl"?>
<๋„์„œ๋ชฉ๋ก>
  <๋„์„œ id="001" ์นดํ…Œ๊ณ ๋ฆฌ="ํ”„๋กœ๊ทธ๋ž˜๋ฐ" ์ถ”์ฒœ="true">
    <์ œ๋ชฉ>XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ</์ œ๋ชฉ>
    <์ €์ž>ํ™๊ธธ๋™</์ €์ž>
    <์ถœํŒ์‚ฌ>ํ…Œํฌ๋ถ์Šค</์ถœํŒ์‚ฌ>
    <์ถœํŒ๋…„๋„>2024</์ถœํŒ๋…„๋„>
    <๊ฐ€๊ฒฉ>28000</๊ฐ€๊ฒฉ>
    <์žฌ๊ณ >15</์žฌ๊ณ >
  </๋„์„œ>
  <๋„์„œ id="002" ์นดํ…Œ๊ณ ๋ฆฌ="์›น๊ฐœ๋ฐœ">
    <์ œ๋ชฉ>XSLT ์‹ค์ „ ๊ฐ€์ด๋“œ</์ œ๋ชฉ>
    <์ €์ž>๊น€์ฒ ์ˆ˜</์ €์ž>
    <์ถœํŒ์‚ฌ>์ฝ”๋”ฉํ•˜์šฐ์Šค</์ถœํŒ์‚ฌ>
    <์ถœํŒ๋…„๋„>2023</์ถœํŒ๋…„๋„>
    <๊ฐ€๊ฒฉ>32000</๊ฐ€๊ฒฉ>
    <์žฌ๊ณ >0</์žฌ๊ณ >
  </๋„์„œ>
  <๋„์„œ id="003" ์นดํ…Œ๊ณ ๋ฆฌ="ํ”„๋กœ๊ทธ๋ž˜๋ฐ" ์ถ”์ฒœ="true">
    <์ œ๋ชฉ>XPath ์™„๋ฒฝ ๋ ˆ์‹œํ”ผ</์ œ๋ชฉ>
    <์ €์ž>์ด์˜ํฌ</์ €์ž>
    <์ถœํŒ์‚ฌ>๋ฐ์ดํ„ฐ๋ถ</์ถœํŒ์‚ฌ>
    <์ถœํŒ๋…„๋„>2024</์ถœํŒ๋…„๋„>
    <๊ฐ€๊ฒฉ>25000</๊ฐ€๊ฒฉ>
    <์žฌ๊ณ >8</์žฌ๊ณ >
  </๋„์„œ>
</๋„์„œ๋ชฉ๋ก>
โš™๏ธ XSLT ์Šคํƒ€์ผ์‹œํŠธ (books.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" encoding="UTF-8" indent="yes"
    doctype-public="-//W3C//DTD HTML 4.01//EN"/>

  <!-- ์ „์—ญ ๋ณ€์ˆ˜ -->
  <xsl:variable name="์ด๋„์„œ์ˆ˜" select="count(//๋„์„œ)"/>
  <xsl:variable name="์ด์žฌ๊ณ " select="sum(//์žฌ๊ณ )"/>
  <xsl:variable name="ํ‰๊ท ๊ฐ€๊ฒฉ"
    select="sum(//๊ฐ€๊ฒฉ) div $์ด๋„์„œ์ˆ˜"/>

  <!-- ๋ฃจํŠธ ํ…œํ”Œ๋ฆฟ -->
  <xsl:template match="/">
    <html>
    <head>
      <title>๋„์„œ ๋ชฉ๋ก</title>
      <style>
        table { border-collapse: collapse; width: 100%; }
        th { background: #7ab3cc; color: white; padding: 10px; }
        td { padding: 8px; border-bottom: 1px solid #ddd; }
        .์ถ”์ฒœ { background: #fffde7; }
        .ํ’ˆ์ ˆ { color: red; font-weight: bold; }
        .ํ†ต๊ณ„ { background: #f4f9fc; padding: 12px; margin-bottom: 16px; }
      </style>
    </head>
    <body>
      <h1>๐Ÿ“š ๋„์„œ ๋ชฉ๋ก</h1>

      <!-- ํ†ต๊ณ„ ์„น์…˜ -->
      <div class="ํ†ต๊ณ„">
        <strong>์ด ๋„์„œ ์ˆ˜:</strong>
        <xsl:value-of select="$์ด๋„์„œ์ˆ˜"/>๊ถŒ |
        <strong>์ด ์žฌ๊ณ :</strong>
        <xsl:value-of select="$์ด์žฌ๊ณ "/>๊ถŒ |
        <strong>ํ‰๊ท  ๊ฐ€๊ฒฉ:</strong>
        <xsl:value-of select="format-number($ํ‰๊ท ๊ฐ€๊ฒฉ,'#,###')"/>์›
      </div>

      <table>
        <tr>
          <th>๋ฒˆํ˜ธ</th>
          <th>์ œ๋ชฉ</th>
          <th>์ €์ž</th>
          <th>์นดํ…Œ๊ณ ๋ฆฌ</th>
          <th>๊ฐ€๊ฒฉ</th>
          <th>์žฌ๊ณ </th>
        </tr>
        <!-- ๊ฐ€๊ฒฉ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ -->
        <xsl:apply-templates select="๋„์„œ๋ชฉ๋ก/๋„์„œ">
          <xsl:sort select="๊ฐ€๊ฒฉ" data-type="number"/>
        </xsl:apply-templates>
      </table>
    </body>
    </html>
  </xsl:template>

  <!-- ๋„์„œ ํ–‰ ํ…œํ”Œ๋ฆฟ -->
  <xsl:template match="๋„์„œ">
    <tr>
      <!-- ์ถ”์ฒœ ๋„์„œ๋Š” ๋ฐฐ๊ฒฝ์ƒ‰ ๋‹ค๋ฅด๊ฒŒ -->
      <xsl:if test="@์ถ”์ฒœ='true'">
        <xsl:attribute name="class">์ถ”์ฒœ</xsl:attribute>
      </xsl:if>

      <td><xsl:value-of select="position()"/></td>
      <td>
        <xsl:value-of select="์ œ๋ชฉ"/>
        <xsl:if test="@์ถ”์ฒœ='true'"> โญ</xsl:if>
      </td>
      <td><xsl:value-of select="์ €์ž"/></td>
      <td><xsl:value-of select="@์นดํ…Œ๊ณ ๋ฆฌ"/></td>
      <td>
        <xsl:value-of select="format-number(๊ฐ€๊ฒฉ,'#,###')"/>์›
      </td>
      <td>
        <xsl:choose>
          <xsl:when test="์žฌ๊ณ  = 0">
            <span class="ํ’ˆ์ ˆ">ํ’ˆ์ ˆ</span>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="์žฌ๊ณ "/>๊ถŒ
          </xsl:otherwise>
        </xsl:choose>
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>
๐Ÿ’ก ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฐ”๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ!
XML ํŒŒ์ผ์—
<?xml-stylesheet type="text/xsl" href="books.xsl"?>
๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด
๋ธŒ๋ผ์šฐ์ €(Chrome, Firefox)์—์„œ XML ํŒŒ์ผ์„ ์—ด์—ˆ์„ ๋•Œ ์ž๋™์œผ๋กœ XSLT ๋ณ€ํ™˜์ด ์ ์šฉ๋ผ!
๋‹จ, Chrome์€ ๋กœ์ปฌ ํŒŒ์ผ ๋ณด์•ˆ ์ •์ฑ…์œผ๋กœ ์„œ๋ฒ„ ํ™˜๊ฒฝ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์–ด.

๐Ÿ› ๏ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋ณ„ XML/XSLT ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

์‹ค์ œ ๊ฐœ๋ฐœ์—์„œ๋Š” ๋ธŒ๋ผ์šฐ์ € ๋ Œ๋”๋ง๋ณด๋‹ค ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ํ›จ์”ฌ ๋งŽ์•„.
์ฃผ์š” ์–ธ์–ด๋ณ„๋กœ ์–ด๋–ป๊ฒŒ XML๊ณผ XSLT๋ฅผ ๋‹ค๋ฃจ๋Š”์ง€ ์•Œ์•„๋ณด์ž! ๐Ÿ–ฅ๏ธ

โ˜• Java - JAXP (Java API for XML Processing)
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class XSLTProcessor {
    public static void main(String[] args) throws Exception {
        // TransformerFactory ์ƒ์„ฑ
        TransformerFactory factory = TransformerFactory.newInstance();

        // XSLT ์Šคํƒ€์ผ์‹œํŠธ ๋กœ๋“œ
        Source xslt = new StreamSource(new File("books.xsl"));
        Transformer transformer = factory.newTransformer(xslt);

        // ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ (์„ ํƒ์‚ฌํ•ญ)
        transformer.setParameter("์„ ํƒ์นดํ…Œ๊ณ ๋ฆฌ", "ํ”„๋กœ๊ทธ๋ž˜๋ฐ");

        // ๋ณ€ํ™˜ ์‹คํ–‰
        Source xml = new StreamSource(new File("books.xml"));
        Result output = new StreamResult(new File("output.html"));
        transformer.transform(xml, output);

        System.out.println("๋ณ€ํ™˜ ์™„๋ฃŒ!");
    }
}
๐Ÿ Python - lxml ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
from lxml import etree

# XML ํŒŒ์‹ฑ
xml_doc = etree.parse('books.xml')

# XSLT ์Šคํƒ€์ผ์‹œํŠธ ๋กœ๋“œ
xslt_doc = etree.parse('books.xsl')
transform = etree.XSLT(xslt_doc)

# ํŒŒ๋ผ๋ฏธํ„ฐ ์ „๋‹ฌ (๋ฌธ์ž์—ด์€ ๋”ฐ์˜ดํ‘œ ํฌํ•จ!)
params = {
    '์„ ํƒ์นดํ…Œ๊ณ ๋ฆฌ': etree.XSLT.strparam('ํ”„๋กœ๊ทธ๋ž˜๋ฐ')
}

# ๋ณ€ํ™˜ ์‹คํ–‰
result = transform(xml_doc, **params)

# ๊ฒฐ๊ณผ ์ €์žฅ
with open('output.html', 'wb') as f:
    f.write(bytes(result))

# XPath๋กœ ๋…ธ๋“œ ์„ ํƒ
root = xml_doc.getroot()
titles = root.xpath('//์ œ๋ชฉ/text()')
print(titles)  # ['XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ', 'XSLT ์‹ค์ „ ๊ฐ€์ด๋“œ', ...]

# ์กฐ๊ฑด๋ถ€ XPath
expensive = root.xpath('//๋„์„œ[๊ฐ€๊ฒฉ > 30000]/์ œ๋ชฉ/text()')
print(expensive)
๐ŸŸฆ JavaScript (Node.js) - xslt4node
const xslt4node = require('xslt4node');
const fs = require('fs');

// ์„ค์ • ๊ฐ์ฒด
const config = {
    xsltPath: 'books.xsl',
    sourcePath: 'books.xml',
    result: 'output.html',
    params: {
        '์„ ํƒ์นดํ…Œ๊ณ ๋ฆฌ': 'string:ํ”„๋กœ๊ทธ๋ž˜๋ฐ'
    }
};

// ๋ณ€ํ™˜ ์‹คํ–‰
xslt4node.transform(config, (err) => {
    if (err) {
        console.error('๋ณ€ํ™˜ ์˜ค๋ฅ˜:', err);
    } else {
        console.log('๋ณ€ํ™˜ ์„ฑ๊ณต!');
    }
});

// ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” DOMParser + XSLTProcessor ์‚ฌ์šฉ
const parser = new DOMParser();
const xsltProcessor = new XSLTProcessor();

fetch('books.xsl')
  .then(r => r.text())
  .then(xsltText => {
    const xsltDoc = parser.parseFromString(xsltText, 'text/xml');
    xsltProcessor.importStylesheet(xsltDoc);
    return fetch('books.xml');
  })
  .then(r => r.text())
  .then(xmlText => {
    const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
    const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
    document.body.appendChild(resultDoc.documentElement);
  });
๐Ÿ”ท C# - System.Xml.Xsl
using System.Xml;
using System.Xml.Xsl;

class Program {
    static void Main() {
        // XslCompiledTransform ์‚ฌ์šฉ (์„ฑ๋Šฅ ์ตœ์ ํ™”)
        var xslt = new XslCompiledTransform();
        xslt.Load("books.xsl");

        // ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
        var args = new XsltArgumentList();
        args.AddParam("์„ ํƒ์นดํ…Œ๊ณ ๋ฆฌ", "", "ํ”„๋กœ๊ทธ๋ž˜๋ฐ");

        // ๋ณ€ํ™˜ ์‹คํ–‰
        using var writer = new XmlTextWriter("output.html",
            System.Text.Encoding.UTF8);
        xslt.Transform("books.xml", args, writer);

        Console.WriteLine("๋ณ€ํ™˜ ์™„๋ฃŒ!");
    }
}

๐ŸŽ“ XSLT ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•๋“ค

๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋‹ค์กŒ์œผ๋ฉด ์ด์ œ ์ข€ ๋” ๊ณ ๊ธ‰ ๊ธฐ๋ฒ•๋“ค์„ ์‚ดํŽด๋ณด์ž.
์ด๊ฑธ ์•Œ๋ฉด ์ง„์งœ XSLT ๊ณ ์ˆ˜ ์†Œ๋ฆฌ ๋“ค์„ ์ˆ˜ ์žˆ์–ด! ๐Ÿ˜Ž

๐Ÿ” ์žฌ๊ท€ ํ…œํ”Œ๋ฆฟ - ๋ฌดํ•œ ๋ฐ˜๋ณต์˜ ๋งˆ๋ฒ•

XSLT์—๋Š” ๋ฃจํ”„๊ฐ€ ์—†์–ด์„œ ๋ณต์žกํ•œ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ๋Š” ์žฌ๊ท€ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•ด.
์ฒ˜์Œ์—” ์–ด์ƒ‰ํ•˜์ง€๋งŒ ์ต์ˆ™ํ•ด์ง€๋ฉด ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ผ!

<!-- ์ˆซ์ž๋ฅผ N๋ฒˆ ๋ฐ˜๋ณต ์ถœ๋ ฅํ•˜๋Š” ์žฌ๊ท€ ํ…œํ”Œ๋ฆฟ -->
<xsl:template name="๋ฐ˜๋ณต์ถœ๋ ฅ">
  <xsl:param name="ํšŸ์ˆ˜" select="0"/>
  <xsl:param name="ํ˜„์žฌ" select="1"/>
  <xsl:param name="ํ…์ŠคํŠธ"/>

  <xsl:if test="$ํ˜„์žฌ <= $ํšŸ์ˆ˜">
    <xsl:value-of select="$ํ…์ŠคํŠธ"/>
    <!-- ์žฌ๊ท€ ํ˜ธ์ถœ -->
    <xsl:call-template name="๋ฐ˜๋ณต์ถœ๋ ฅ">
      <xsl:with-param name="ํšŸ์ˆ˜" select="$ํšŸ์ˆ˜"/>
      <xsl:with-param name="ํ˜„์žฌ" select="$ํ˜„์žฌ + 1"/>
      <xsl:with-param name="ํ…์ŠคํŠธ" select="$ํ…์ŠคํŠธ"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

<!-- ํ˜ธ์ถœ ์˜ˆ์‹œ: "โ˜…"์„ 5๋ฒˆ ์ถœ๋ ฅ -->
<xsl:call-template name="๋ฐ˜๋ณต์ถœ๋ ฅ">
  <xsl:with-param name="ํšŸ์ˆ˜" select="5"/>
  <xsl:with-param name="ํ…์ŠคํŠธ">โ˜…</xsl:with-param>
</xsl:call-template>
๐Ÿท๏ธ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ฒ˜๋ฆฌ

์‹ค๋ฌด์—์„œ XML์„ ๋‹ค๋ฃจ๋‹ค ๋ณด๋ฉด ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋•Œ๋ฌธ์— ๊ณจ์น˜ ์•„ํ”ˆ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„.
ํŠนํžˆ SOAP ์›น์„œ๋น„์Šค๋‚˜ Office XML ํŒŒ์ผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ž์ฃผ ๋งŒ๋‚˜๊ฒŒ ๋ผ.

<!-- ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ์žˆ๋Š” XML -->
<root xmlns:์ฑ…="http://example.com/book"
      xmlns:์ €์ž="http://example.com/author">
  <์ฑ…:๋„์„œ>
    <์ฑ…:์ œ๋ชฉ>XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ</์ฑ…:์ œ๋ชฉ>
    <์ €์ž:์ด๋ฆ„>ํ™๊ธธ๋™</์ €์ž:์ด๋ฆ„>
  </์ฑ…:๋„์„œ>
</root>

<!-- XSLT์—์„œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์„ ์–ธ ํ›„ ์‚ฌ์šฉ -->
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:์ฑ…="http://example.com/book"
  xmlns:์ €์ž="http://example.com/author">

  <xsl:template match="/">
    <!-- ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ ‘๋‘์‚ฌ๋กœ ์š”์†Œ ์„ ํƒ -->
    <xsl:value-of select="//์ฑ…:์ œ๋ชฉ"/>
    <xsl:value-of select="//์ €์ž:์ด๋ฆ„"/>
  </xsl:template>

</xsl:stylesheet>
๐Ÿ“Š Muenchian ๊ทธ๋ฃนํ•‘ - ๋ฐ์ดํ„ฐ ์ง‘๊ณ„์˜ ํ•ต์‹ฌ

XSLT 1.0์—์„œ SQL์˜ GROUP BY ๊ฐ™์€ ๊ทธ๋ฃนํ•‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ณ ์ „์ ์ธ ๊ธฐ๋ฒ•์ด์•ผ.
xsl:key๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ, ์•Œ์•„๋‘๋ฉด ์ •๋ง ์œ ์šฉํ•ด!

<!-- ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๊ทธ๋ฃนํ•‘ (Muenchian ๋ฐฉ๋ฒ•) -->

<!-- 1๋‹จ๊ณ„: key ์ •์˜ -->
<xsl:key name="์นดํ…Œ๊ณ ๋ฆฌ๋ณ„" match="๋„์„œ" use="@์นดํ…Œ๊ณ ๋ฆฌ"/>

<!-- 2๋‹จ๊ณ„: ๊ณ ์œ  ์นดํ…Œ๊ณ ๋ฆฌ๋งŒ ์„ ํƒ -->
<xsl:template match="/">
  <xsl:for-each select="//๋„์„œ[
    generate-id() = generate-id(
      key('์นดํ…Œ๊ณ ๋ฆฌ๋ณ„', @์นดํ…Œ๊ณ ๋ฆฌ)[1]
    )
  ]">
    <h2>๐Ÿ“‚ <xsl:value-of select="@์นดํ…Œ๊ณ ๋ฆฌ"/></h2>

    <!-- 3๋‹จ๊ณ„: ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ชจ๋“  ๋„์„œ ์ถœ๋ ฅ -->
    <xsl:for-each select="key('์นดํ…Œ๊ณ ๋ฆฌ๋ณ„', @์นดํ…Œ๊ณ ๋ฆฌ)">
      <p>- <xsl:value-of select="์ œ๋ชฉ"/></p>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>
โš ๏ธ XSLT 1.0์˜ ํ•œ๊ณ„
XSLT 1.0์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ํ•œ๊ณ„๊ฐ€ ์žˆ์–ด:
- ๋ณ€์ˆ˜ ๊ฐ’ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€ (ํ•จ์ˆ˜ํ˜• ํŠน์„ฑ)
- ์ •๊ทœํ‘œํ˜„์‹ ๋ฏธ์ง€์›
- ๋‚ ์งœ/์‹œ๊ฐ„ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜ ์—†์Œ
- ๋ณต์žกํ•œ ๋ฌธ์ž์—ด ์ฒ˜๋ฆฌ ์–ด๋ ค์›€
์ด๋Ÿฐ ๊ฒฝ์šฐ์—” XSLT 2.0/3.0์ด๋‚˜ extension ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด์•ผ ํ•ด!

๐ŸŒ XML Schema (XSD) - ๋ฌธ์„œ์˜ ์„ค๊ณ„๋„

XML์„ ์ œ๋Œ€๋กœ ๋‹ค๋ฃจ๋ ค๋ฉด XML Schema Definition(XSD)๋„ ์•Œ์•„์•ผ ํ•ด.
XSD๋Š” XML ๋ฌธ์„œ์˜ ๊ตฌ์กฐ, ๋ฐ์ดํ„ฐ ํƒ€์ž…, ์ œ์•ฝ ์กฐ๊ฑด์„ ์ •์˜ํ•˜๋Š” ์–ธ์–ด์•ผ.
๋งˆ์น˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์Šคํ‚ค๋งˆ์ฒ˜๋Ÿผ, XML ๋ฌธ์„œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ํ˜•์‹์ธ์ง€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์–ด. ๐Ÿ“‹

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- ๋„์„œ๋ชฉ๋ก ๋ฃจํŠธ ์š”์†Œ ์ •์˜ -->
  <xs:element name="๋„์„œ๋ชฉ๋ก">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="๋„์„œ" type="๋„์„œํƒ€์ž…"
          minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <!-- ๋„์„œ ํƒ€์ž… ์ •์˜ -->
  <xs:complexType name="๋„์„œํƒ€์ž…">
    <xs:sequence>
      <xs:element name="์ œ๋ชฉ" type="xs:string"/>
      <xs:element name="์ €์ž" type="xs:string"/>
      <xs:element name="์ถœํŒ๋…„๋„">
        <xs:simpleType>
          <xs:restriction base="xs:integer">
            <xs:minInclusive value="1900"/>
            <xs:maxInclusive value="2099"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="๊ฐ€๊ฒฉ" type="xs:positiveInteger"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:string" use="required"/>
    <xs:attribute name="์นดํ…Œ๊ณ ๋ฆฌ" use="required">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="ํ”„๋กœ๊ทธ๋ž˜๋ฐ"/>
          <xs:enumeration value="์›น๊ฐœ๋ฐœ"/>
          <xs:enumeration value="๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
  </xs:complexType>

</xs:schema>

๐Ÿ’ผ ์‹ค๋ฌด์—์„œ XML/XSLT๊ฐ€ ์“ฐ์ด๋Š” ๊ณณ๋“ค

"์š”์ฆ˜ JSON์ด ๋Œ€์„ธ์ธ๋ฐ XML์ด ์•„์ง๋„ ์“ฐ์—ฌ?" ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ,
์‹ค์ œ๋กœ XML์€ ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์€ ๊ณณ์—์„œ ์—ฌ์ „ํžˆ ํ•ต์‹ฌ ๊ธฐ์ˆ ๋กœ ํ™œ์šฉ๋˜๊ณ  ์žˆ์–ด! ๐Ÿญ

๐Ÿฆ ๊ธˆ์œต/๊ณต๊ณต
์ „์ž์„ธ๊ธˆ๊ณ„์‚ฐ์„œ, ๊ธˆ์œต EDI, ๊ณต๊ณต ๋ฐ์ดํ„ฐ API, ์ „์ž์ •๋ถ€ ํ‘œ์ค€ํ”„๋ ˆ์ž„์›Œํฌ
๐Ÿ“Š ์ถœํŒ/์ธ์‡„
DocBook, DITA, XSL-FO๋กœ PDF ์ƒ์„ฑ, ์ „์ž์ฑ…(EPUB) ์ œ์ž‘
๐Ÿข ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ
SOAP ์›น์„œ๋น„์Šค, SAP/Oracle ERP ์—ฐ๋™, ESB ๋ฉ”์‹œ์ง€ ๋ณ€ํ™˜
๐Ÿ“ฑ ๋ชจ๋ฐ”์ผ/์•ฑ
Android ๋ ˆ์ด์•„์›ƒ, iOS plist, ์•ฑ ์„ค์ • ํŒŒ์ผ, ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ
๐ŸŒ ์›น ํ‘œ์ค€
SVG, MathML, RSS/Atom ํ”ผ๋“œ, XHTML, WSDL
๐Ÿ”ง ๊ฐœ๋ฐœ ๋„๊ตฌ
Maven/Ant ๋นŒ๋“œ ์„ค์ •, Spring ์„ค์ •, JUnit ๋ฆฌํฌํŠธ
๐Ÿ’ก ์žฌ๋Šฅ๋„ท์—์„œ๋„ XML/XSLT ๊ด€๋ จ ์žฌ๋Šฅ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด!
์žฌ๋Šฅ๋„ท์—์„œ๋Š” XML ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ, XSLT ๋ณ€ํ™˜ ์Šคํฌ๋ฆฝํŠธ ๊ฐœ๋ฐœ, XML Schema ์„ค๊ณ„ ๊ฐ™์€
์ „๋ฌธ์ ์ธ XML ๊ด€๋ จ ๊ฐœ๋ฐœ ์žฌ๋Šฅ์„ ๊ฑฐ๋ž˜ํ•  ์ˆ˜ ์žˆ์–ด. ํ”„๋ฆฌ๋žœ์„œ ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ์ด๋Ÿฐ ํ‹ˆ์ƒˆ ๊ธฐ์ˆ ์ด
๊ฒฝ์Ÿ๋ ฅ์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑฐ ์•Œ์•„๋‘ฌ! ๐Ÿ˜‰

โšก XML vs JSON - ์–ธ์ œ ๋ฌด์—‡์„ ์“ธ๊นŒ? ๐Ÿ“„ XML์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ ๋ณต์žกํ•œ ๋ฌธ์„œ ๊ตฌ์กฐ ํ‘œํ˜„ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ XSLT๋กœ ๋‹ค์–‘ํ•œ ํ˜•์‹ ๋ณ€ํ™˜ ๊ธˆ์œตยท๊ณต๊ณต ํ‘œ์ค€ ๋ฌธ์„œ ํ˜ผํ•ฉ ์ฝ˜ํ…์ธ  (ํ…์ŠคํŠธ+ํƒœ๊ทธ) ์ฃผ์„ยท์ฒ˜๋ฆฌ ๋ช…๋ น์–ด ํ•„์š” ์‹œ ๐Ÿ”ท JSON์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ REST API ๋ฐ์ดํ„ฐ ๊ตํ™˜ JavaScript ์นœํ™”์  ํ™˜๊ฒฝ ๊ฐ€๋ณ๊ณ  ๋น ๋ฅธ ํŒŒ์‹ฑ ํ•„์š” ๋ชจ๋ฐ”์ผ ์•ฑ API ํ†ต์‹  NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ €์žฅ ๋‹จ์ˆœ ํ‚ค-๊ฐ’ ๊ตฌ์กฐ ๋ฐ์ดํ„ฐ VS

๐Ÿ”ง XSLT ๋””๋ฒ„๊น… & ๊ฐœ๋ฐœ ๋„๊ตฌ

XSLT ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด "์™œ ์•ˆ ๋˜์ง€?" ํ•˜๋Š” ์ˆœ๊ฐ„์ด ๋ฐ˜๋“œ์‹œ ์™€. ๐Ÿ˜…
๊ทธ๋Ÿด ๋•Œ ๋„์›€์ด ๋˜๋Š” ๋„๊ตฌ๋“ค์„ ์†Œ๊ฐœํ• ๊ฒŒ!

๋„๊ตฌ์ข…๋ฅ˜ํŠน์ง•
Saxon HE/PE/EEXSLT ํ”„๋กœ์„ธ์„œXSLT 2.0/3.0 ์ง€์›, ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์„ธ์„œ
Oxygen XML EditorIDEXML/XSLT ์ „์šฉ IDE, ๋””๋ฒ„๊ฑฐ ๋‚ด์žฅ, ์œ ๋ฃŒ
Altova XMLSpyIDE์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ XML ๊ฐœ๋ฐœ ํ™˜๊ฒฝ, ์œ ๋ฃŒ
VS Code + XML ํ™•์žฅ์—๋””ํ„ฐ๋ฌด๋ฃŒ, Red Hat XML ํ™•์žฅ์œผ๋กœ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๊ฐ€๋Šฅ
xsltprocCLI ๋„๊ตฌ๋ฆฌ๋ˆ…์Šค ๊ธฐ๋ณธ ํƒ‘์žฌ, libxslt ๊ธฐ๋ฐ˜, ๋น ๋ฅธ ์ฒ˜๋ฆฌ
Online XSLT Tester์›น ๋„๊ตฌxsltransform.net ๋“ฑ, ๋น ๋ฅธ ํ…Œ์ŠคํŠธ์šฉ
๐Ÿ› ์ž์ฃผ ๋งŒ๋‚˜๋Š” XSLT ์˜ค๋ฅ˜์™€ ํ•ด๊ฒฐ๋ฒ•
โ‘  ๋นˆ ์ถœ๋ ฅ ๋ฌธ์ œ
xsl:template match์˜ XPath๊ฐ€ ์ž˜๋ชป๋์„ ๋•Œ ๋ฐœ์ƒ.
โ†’ xsl:message๋กœ ์ค‘๊ฐ„ ๊ฐ’ ์ถœ๋ ฅํ•ด์„œ ๋””๋ฒ„๊น…ํ•˜๊ฑฐ๋‚˜, XPath๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ด.
โ‘ก ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์˜ค๋ฅ˜
์†Œ์Šค XML์— ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ์žˆ๋Š”๋ฐ XSLT์—์„œ ์„ ์–ธ ์•ˆ ํ–ˆ์„ ๋•Œ.
โ†’ XSLT ๋ฃจํŠธ ์š”์†Œ์— ๋™์ผํ•œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค URI๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•ด.
โ‘ข ๋ฌดํ•œ ์žฌ๊ท€
xsl:apply-templates๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ๊ณ„์† ํ˜ธ์ถœํ•  ๋•Œ.
โ†’ select ์†์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ๋…ธ๋“œ๋ฅผ ๋ช…ํ™•ํžˆ ์ง€์ •ํ•ด์•ผ ํ•ด.
<!-- ๋””๋ฒ„๊น…์šฉ xsl:message ํ™œ์šฉ -->
<xsl:template match="๋„์„œ">
  <!-- ์ฝ˜์†”์— ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ (terminate="yes"๋ฉด ์ฒ˜๋ฆฌ ์ค‘๋‹จ) -->
  <xsl:message>
    ํ˜„์žฌ ์ฒ˜๋ฆฌ ์ค‘์ธ ๋„์„œ: <xsl:value-of select="์ œ๋ชฉ"/>
    ๊ฐ€๊ฒฉ: <xsl:value-of select="๊ฐ€๊ฒฉ"/>
  </xsl:message>
  <!-- ์‹ค์ œ ์ฒ˜๋ฆฌ ๋‚ด์šฉ -->
</xsl:template>

๐Ÿš€ XSLT 3.0์˜ ์ƒˆ๋กœ์šด ์„ธ๊ณ„

2017๋…„์— W3C ํ‘œ์ค€์ด ๋œ XSLT 3.0์€ ๊ธฐ์กด์˜ ํ•œ๊ณ„๋ฅผ ๋งŽ์ด ๊ทน๋ณตํ–ˆ์–ด.
Saxon 9.8+ ๋ฒ„์ „์—์„œ ์™„์ „ ์ง€์›ํ•˜๊ณ , ํ˜„๋Œ€์ ์ธ ๊ฐœ๋ฐœ ํŒจํ„ด์„ ๋งŽ์ด ๋„์ž…ํ–ˆ์ง€. ๐Ÿ†•

๐Ÿ“ฆ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ
์ˆ˜ GB์งœ๋ฆฌ XML๋„ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
๐Ÿ—บ๏ธ ๋งต๊ณผ ๋ฐฐ์—ด
JSON๊ณผ ์œ ์‚ฌํ•œ ๋งต/๋ฐฐ์—ด ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ง€์›
๐Ÿ”„ JSON ์ฒ˜๋ฆฌ
json-to-xml(), xml-to-json() ํ•จ์ˆ˜๋กœ JSON ๋ณ€ํ™˜
<!-- XSLT 3.0: JSON์„ XML๋กœ ๋ณ€ํ™˜ ํ›„ ์ฒ˜๋ฆฌ -->
<xsl:stylesheet version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template name="xsl:initial-template">
    <!-- JSON ๋ฌธ์ž์—ด์„ XML๋กœ ๋ณ€ํ™˜ -->
    <xsl:variable name="json-text">
      {"๋„์„œ": [{"์ œ๋ชฉ": "XML ๋งˆ์Šคํ„ฐํ•˜๊ธฐ", "๊ฐ€๊ฒฉ": 28000}]}
    </xsl:variable>

    <xsl:variable name="xml-data"
      select="json-to-xml($json-text)"/>

    <!-- ๋ณ€ํ™˜๋œ XML ์ฒ˜๋ฆฌ -->
    <xsl:for-each select="$xml-data//map[@key='๋„์„œ']/map">
      <p><xsl:value-of select="string[@key='์ œ๋ชฉ']"/></p>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

๐Ÿ“š ํ•™์Šต ๋กœ๋“œ๋งต๊ณผ ์ถ”์ฒœ ๋ฆฌ์†Œ์Šค

XML/XSLT/XPath๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด ์ด ์ˆœ์„œ๋กœ ๊ณต๋ถ€ํ•ด๋ด!
๊ทธ๋ฆฌ๊ณ  ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์‹ค์ œ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜์„ ์Œ“๋Š” ๊ฒƒ๋„ ์ •๋ง ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๐Ÿ“–

๐Ÿ—“๏ธ ๋‹จ๊ณ„๋ณ„ ํ•™์Šต ๋กœ๋“œ๋งต

1๋‹จ๊ณ„ (1~2์ฃผ): XML ๊ธฐ๋ณธ ๋ฌธ๋ฒ•, Well-formed/Valid ๊ฐœ๋…, DTD ๊ธฐ์ดˆ
2๋‹จ๊ณ„ (2~3์ฃผ): XPath 1.0 ์™„์ „ ์ •๋ณต - ์ถ•, ํ•จ์ˆ˜, ์กฐ๊ฑด์‹
3๋‹จ๊ณ„ (3~4์ฃผ): XSLT 1.0 ํ•ต์‹ฌ ์š”์†Œ - template, for-each, if/choose
4๋‹จ๊ณ„ (2~3์ฃผ): XML Schema(XSD) ์„ค๊ณ„ ๋ฐ ๊ฒ€์ฆ
5๋‹จ๊ณ„ (์ง€์†): ์‹ค์ „ ํ”„๋กœ์ ํŠธ - ์‹ค์ œ XML ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์ž‘์—…
6๋‹จ๊ณ„ (์„ ํƒ): XSLT 2.0/3.0, XPath 2.0, Saxon ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ
๐Ÿ“– ์ถ”์ฒœ ํ•™์Šต ์ž๋ฃŒ
์ž๋ฃŒํŠน์ง•
W3Schools XML/XSLT ํŠœํ† ๋ฆฌ์–ผ๋ฌด๋ฃŒ, ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์˜ˆ์ œ, ์ž…๋ฌธ์ž ์ตœ์ 
W3C ๊ณต์‹ ์ŠคํŽ™๊ฐ€์žฅ ์ •ํ™•ํ•œ ๋ ˆํผ๋Ÿฐ์Šค, ์˜์–ด
XSLT 2.0 and XPath 2.0 (Michael Kay)Saxon ๊ฐœ๋ฐœ์ž๊ฐ€ ์“ด ๋ฐ”์ด๋ธ”, ์‹ฌํ™” ํ•™์Šต
XPath and XPointer (John Simpson)XPath ์ „๋ฌธ์„œ, O'Reilly
Stack Overflow xml ํƒœ๊ทธ์‹ค๋ฌด ๋ฌธ์ œ ํ•ด๊ฒฐ์˜ ๋ณด๊ณ 
๐Ÿ’ก ์‹ค๋ ฅ ํ–ฅ์ƒ ๊ฟ€ํŒ!
๊ณต๊ณต๋ฐ์ดํ„ฐํฌํ„ธ(data.go.kr)์—์„œ XML ํ˜•์‹์˜ ๊ณต๊ณต API๋ฅผ ๋ฐ›์•„์„œ
XSLT๋กœ HTML ๋ฆฌํฌํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ์—ฐ์Šต์ด ์ตœ๊ณ ์•ผ.
์‹ค์ œ ๋ฐ์ดํ„ฐ๋กœ ์ž‘์—…ํ•˜๋ฉด ์ด๋ก ๋งŒ ๊ณต๋ถ€ํ•  ๋•Œ์™€ ์ฐจ์›์ด ๋‹ค๋ฅธ ์ดํ•ด๊ฐ€ ์ƒ๊ฒจ! ๐ŸŽฏ

๐ŸŽฏ ๋งˆ๋ฌด๋ฆฌ - XML ํŠธ๋ฆฌ์˜ค์˜ ์ง„์งœ ๊ฐ€์น˜

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ XML, XPath, XSLT์˜ ์„ธ๊ณ„๋ฅผ ํ•จ๊ป˜ ํƒํ—˜ํ•ด๋ดค์–ด! ๐ŸŽ‰
์ฒ˜์Œ์—” ๋ณต์žกํ•ด ๋ณด์ด์ง€๋งŒ, ์ด ์„ธ ๊ธฐ์ˆ ์€ ์„œ๋กœ ์™„๋ฒฝํ•˜๊ฒŒ ๋งž๋ฌผ๋ ค์„œ ๋™์ž‘ํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ์ƒํƒœ๊ณ„์•ผ.

XML์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๊ณ ,
XPath๋Š” ๊ทธ ๊ตฌ์กฐ ์†์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ •ํ™•ํžˆ ์ฐพ์•„๋‚ด๊ณ ,
XSLT๋Š” ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด๋‚ด์ง€.

JSON์ด ๋Œ€์„ธ์ธ ์‹œ๋Œ€์—๋„ XML์€ ์—ฌ์ „ํžˆ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ, ๊ณต๊ณต, ์ถœํŒ, ํ‘œ์ค€ ๋ฌธ์„œ ๋ถ„์•ผ์—์„œ
์—†์–ด์„œ๋Š” ์•ˆ ๋  ํ•ต์‹ฌ ๊ธฐ์ˆ ์ด์•ผ. ํŠนํžˆ ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ ์—ฐ๋™์ด๋‚˜ ๋ณต์žกํ•œ ๋ฌธ์„œ ๋ณ€ํ™˜ ์ž‘์—…์—์„œ
XML/XSLT ๋Šฅ๋ ฅ์ž๋Š” ์ •๋ง ๊ท€ํ•œ ์กด์žฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์–ด. ๐Ÿ’Ž

๐Ÿ† XML ํŠธ๋ฆฌ์˜ค ํ•ต์‹ฌ ์š”์•ฝ

XML = ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ ํ‘œํ˜„ XPath = ๋…ธ๋“œ ํƒ์ƒ‰ ์–ธ์–ด XSLT = ๋ณ€ํ™˜ ๊ทœ์น™ ์–ธ์–ด XSD = ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ Saxon = ์ตœ๊ฐ• XSLT ํ”„๋กœ์„ธ์„œ lxml = Python XML ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ JAXP = Java XML API

์ด ๊ธ€์„ ๋‹ค ์ฝ์€ ๋„ˆ๋Š” ์ด๋ฏธ XML ํŠธ๋ฆฌ์˜ค์˜ ๊ธฐ์ดˆ๋ฅผ ์™„์ „ํžˆ ์ดํ•ดํ•œ ๊ฑฐ์•ผ! ๐Ÿ‘
์ด์ œ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ณ , ์‹ค์ œ XML ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•ด๋ณด๋ฉด์„œ ์‹ค๋ ฅ์„ ํ‚ค์›Œ๋ด.
๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด W3C ์ŠคํŽ™๊ณผ Stack Overflow๊ฐ€ ํ•ญ์ƒ ๊ณ์— ์žˆ๋‹ค๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ! ๐Ÿš€

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.