XPath
XPath란 ?
XPath는 XML 문서의 특정 요소나 속성에 접근하기 위한 경로를 지정하는 언어이다.
XPath는 W3C 표준 권고안으로, XSLT와 XPointer에 사용될 목적으로 만들어졌다.
또한, XML DOM에서 노드를 검색할 때에도 사용할 수 있다.
현재 가장 최신 버전의 XPath는 2017년 3월 17일에 발표된 XPath 3.1이다.
XPath 3.1에 대한 더 자세한 정보를 원한다면, W3C 공식 사이트를 방문하여 확인할 수 있다.
https://www.w3.org/TR/xpath-31/
XPath의 특징
XPath는 XML 문서의 일부분을 선택하고 처리하기 위해 만들어진 언어이다.
이러한 XPath는 다음과 같은 특징을 가진다.
XPath 노드의 형식
XPath에서 사용하는 노드의 형식은 다음과 같이 구분된다.
XPath 표현식(expression)
XPath에서는 XML 문서의 노드나 노드셋(node-set)을 선택하기 위해 다양한 표현식을 사용한다.
아래 예제에서 사용되는 programming_languages.xml 파일의 코드는 다음과 같다.
Tip : 노드셋(node-set)이란 중복을 허용하지 않는 노드들의 순서없는 집합을 의미한다.
위치 경로(location path)
위치 경로(location path)란 XML 문서의 각 노드의 위치를 지정하기 위한 XPath 표현식이다.
위치 경로는 절대 경로와 상대 경로로 구분할 수 있다.
경로 연산자 |
설명 |
노드 이름 |
해당 '노드 이름'과 일치하는 모든 노드를 선택함. |
/ | 루트 노드부터 순서대로 탐색해 나감. |
// | 현재 노드의 위치와 상관없이 지정된 노드에서부터 순서대로 탐색해 나감. |
. | 현재 노드를 선택함. |
.. | 현재 노드의 부모 노드를 선택함. |
@ | 속성 노드를 선택함. |
예제
developer : <developer> 요소를 모두 선택함.
/p_languages : 루트 노드의 자식 노드인 <p_languages>요소를 선택함. (절대 경로 탐색)
p_languages/language : <p_languages> 요소의 자식 노드 중 <language>요소를 모두 선택함. (상대 경로 탐색)
// : 루트 노드의 하위 노드를 모두 선택함
// priority : 위치에 상관없이 <priority> 요소를 모두 선택함.
.// : 현재 노드의 하위 노드를 모두 선택함.
version/@status : 모든 <version>요소의 status 속성 노드를 모두 선택함.
Tip : 위치 경로가 슬래시(/)로 시작하면 언제나 단 하나의 요소만을 가리키는 절대 경로를 나타낸다.
다음 예제는 위치에 상관없이 <version> 요소를 모두 선택하는 예제이다.
예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <title>XML Xpath</title> <script> function loadDoc() { var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function() { if(this.status == 200 && this.readyState == this.DONE) { findResult(xmlHttp); } }; xmlHttp.open("GET", "/examples/media/programming_languages.xml", true); xmlHttp.send(); } function findResult(xmlHttp) { var xmlObj, path, result, nodeList, node; xmlObj = xmlHttp.responseXML; path = "//version"; result = ""; // 익스플로러를 위한 코드 if (window.ActiveXObject !== undefined || xmlHttp.responseType == "msxml-document") { xmlObj.setProperty("SelectionLanguage", "XPath"); nodeList = xmlObj.selectNodes(path); for (i=0; i<nodeList.length; i++) { result += nodeList[i].text + "<br>"; } // 익스플로러를 제외한 브라우저를 위한 코드 } else if (document.implementation && document.implementation.createDocument) { nodeList = xmlObj.evaluate(path, xmlObj, null, XPathResult.ANY_TYPE, null); node = nodeList.iterateNext(); while (node) { result += node.firstChild.nodeValue + "<br>"; node = nodeList.iterateNext(); } } document.getElementById("text").innerHTML = result; } </script> </head> <body> <h1></h1> <button onclick="loadDoc()">경로 표현식 //version 확인!</button> <p id="text"></p> </body> </html> | cs |
노드를 찾기 위한 검색 방향 설정
XPath에서 검색 방향(axis step)은 현재 노드를 기준으로 어느 방향으로 검색해 나갈지를 명시한다.
XPath에서 사용할 수 있는 검색 방향(axis step)은 다음과 같다.
검색 방향 |
설명 |
self |
현재 노드를 선택함. |
attribute | 현재 노드의 속성 노드를 모두 선택함. |
namespace | 현재 노드의 네임스페이스 노드를 모두 선택함. |
child | 현재 노드의 자식 노드를 모두 선택함. |
descendant | 현재 노드의 자손 노드를 모두 선택함. |
descendant-or-self | 현재 노드와 현재 노드의 자손 노드를 모두 선택함. |
following-sibling | 현재 노드 이후에 위치하는 형제 노드를 모두 선택함. |
parent | 현재 노드의 부모 노드를 선택함. |
ancestor | 현재 노드의 조상 노드를 모두 선택함. |
ancestor-or-self | 현재 노드와 현재 노드의 조상 노드를 모두 선택함. |
preceding | XML 문서에서 현재 노드 이전에 등장하는 모든 노드를 선택함. |
preceding-sibling | 현재 노드 이전에 위치하는 형제 노드를 모두 선택함. |
경로 표현식(path expression)
XPath에서는 노드를 선택하기 위해 경로 표현식(path expression)을 사용한다.
XPath에서 경로 표현식을 작성하는 문법은 다음과 같다.
문법
검색방향::노드테스트[필터표현식]
예제
child::language : 현재 노드의 자식 노드 중 <language>요소를 모두 선택함.
attribute::version : 현재 노드의 version 속성 노드를 선택함.
descendant:::* : 현재 노드의 자손 노드를 모두 선택함.
descendant::text( ) : 현재 노드의 자손 노드 중 텍스트 노드를 모두 선택함.
ancestor::language : 현재 노드의 조상 노드 중 <language>요소를 모두 선택함.
ancestor-or-self::language : 현재 노드와 현재 노드의 조상 노드 중 <language> 요소를 모두 선택함.
child::*/child::category : 현재 노드의 자식 노드의 자식 노드 중 <category> 요소를 모두 선택함.
예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <title>XML Xpath</title> <script> function loadDoc() { var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function() { if(this.status == 200 && this.readyState == this.DONE) { findResult(xmlHttp); } }; xmlHttp.open("GET", "/examples/media/programming_languages.xml", true); xmlHttp.send(); } function findResult(xmlHttp) { var xmlObj, path, result, nodeList, node; xmlObj = xmlHttp.responseXML; path = "descendant::*"; result = ""; // 익스플로러를 위한 코드 if (window.ActiveXObject !== undefined || xmlHttp.responseType == "msxml-document") { xmlObj.setProperty("SelectionLanguage", "XPath"); nodeList = xmlObj.selectNodes(path); for (i=0; i<nodeList.length; i++) { result += nodeList[i].text + "<br>"; } // 익스플로러를 제외한 브라우저를 위한 코드 } else if (document.implementation && document.implementation.createDocument) { nodeList = xmlObj.evaluate(path, xmlObj, null, XPathResult.ANY_TYPE, null); node = nodeList.iterateNext(); while (node) { result += node.firstChild.nodeValue + "<br>"; node = nodeList.iterateNext(); } } document.getElementById("text").innerHTML = result; } </script> </head> <body> <h1></h1> <button onclick="loadDoc()">경로 표현식 descendant::* 확인!</button> <p id="text"></p> </body> </html> | cs |
필터 표현식(filter expressions)
XPath에서는 특정 노드나 특정 값을 포함하는 노드를 선택하기 위해 필터 표현식(filter expressions)을 사용한다.
필터 표현식은 언제나 대괄호([])안에 표현된다.
이러한 필터 표현식에 XPath 함수를 사용하면 더욱 자세한 필터링을 할 수 있다.
예제
p_languages/language[1] : <p_languages> 요소의 자식 노드 중 첫 번째 <language> 요소를 선택함.
p_languages/language[position() < 3] : <p_languages>요소의 자식 노드 중 처음 두 개의 <language>요소를 선택함.
p_languages/language[last()] : <p_languages>요소의 자식 노드 중 마지막<language>요소를 선택함.
//priority[@rating] : rating 속성을 가지고 있는 <priority>요소를 모두 선택함.
//priority[@rating = 3] : rating 속성의 속성값이 3인 <priority>요소를 모두 선택함.
count(//language) : 모든 <language>요소의 개수를 반환함.
XPath 함수
XPath 함수는 선택된 노드셋을 평가하여 조건에 맞는 노드를 시퀀스 형태로 반환한다.
가장 많이 사용되는 XPath 함수는 다음과 같다.
XPath 함수 |
설명 |
position( ) |
현재 노드셋 안에서의 노드의 위치를 반환함. |
last( ) | 현재 노드셋의 마지막 노드를 반환함. |
count(위치경로) | 지정된 노드셋의 총 노드 개수를 반환함. |
name( ) | 현재 노드의 이름을 반환함. |
name(위치경로) | 지정된 노드셋의 첫 번째 노드를 반환함. |
XPath 함수에 대한 더 자세한 정보를 원한다면, W3C 공식 사이트를 방문하여 확인할 수 있다.
https://www.w3.org/TR/xpath-functions-31/
임의 문자 기호(wild card)
임의 문자 기호 |
설명 |
* |
어떠한 요소 노드와도 일치함. |
@* | 어떠한 속성 노드와도 일치함. |
node( ) | 어떠한 종류의 어떤 노드와도 일치함. |
text( ) | 어떠한 텍스트 노드와도 일치함. |
예제
../* : 현재 노드의 부모 노드의 자식 요소 노드를 모두 선택함.
//* : 현재 문서의 모든 요소 노드를 선택함.
//priority[@*] : 어떠한 종류의 속성 노드라도 적어도 하나 이상 가지고 있는 <priority>요소를 모두 선택함.
연산자(operator)
연산자 |
설명 | 반환 타입 |
- |
음의 부호(단항 연산자) | 숫자(number) |
*, div, mod | 곱셈, 나눗셈, 나머지 연산 | 숫자(number) |
+, - | 덧셈, 뺄셈 | 숫자(number) |
<, <=, >, >= | 비교 연산 | 불리언(boolean) |
=, != | 등가 비교 연산 | 불리언(boolean) |
and | 논리 AND 연산 | 불리언(boolean) |
or | 논리 OR 연산 | 불리언(boolean) |
| | 여러 개의 노드셋을 동시에 계산함. | 노드셋(node-set) |
예제
//language/name| //language/version : 모든 <language>요소의 <name>요소와 <version>요소를 모두 선택함.
//name | //version : 현재 문서의 <name>요소와 <version>요소를 모두 선택함.
/language/version/@status | //version : <language>요소의 <version>요소의 status 속성을 모두 선택하고, 현재 문서의 <version> 요소도 모두 선택함.
Tip : 위의 표에서 연산자의 우선순위는 아래에서부터 위쪽으로 증가한다.
즉, 맨 위의 음의 부호가 가장 우선순위가 높으며, | 연산자가 가장 우선순위가 낮다.