치춘짱베리굿나이스

XML 파서와 XPath 본문

ClientSide/기타

XML 파서와 XPath

치춘 2022. 10. 5. 14:25

XML 파서와 XPath

XML 문서를 접근하고 조작하여 읽어들이려면 XML 파서가 필요하다

XML 파서는 인자로 받아온 XML 문서가 제대로 된 XML 문서인지 (문법오류는 없는지, XML 형식이 맞는지 등) 검사하고, 해석한 결과를 반환한다

Parsing? Parser?

주어진 문자열이나 파일을 분석하거나, 정해진 문법 간 관계를 해석하는 것

문서를 읽어들일 때 필수 과정으로, 프로그램에 최적화된 형식으로 파싱하여 간편하게 해당 데이터를 사용할 수 있다

필요한 데이터의 빠른 처리가 가능하고, 설렁 XML 파일이 수정되었다고 해도 같은 파서를 사용하면 수정된 데이터를 같은 방식으로 잘라 가져올 수 있기 때문에 사용이 편리하다

XML 파서를 만드는 이유?

XML 파일 (또는 HTML 파일) 을 파싱하여 DOM 트리로 만들면, DOM 트리를 위한 다양한 메서드들을 사용할 수 있다

예를 들어, 특정 태그에 접근하고 싶을 때 XML 문서 그 자체로는 해당 태그에 접근이 어렵지만, 파싱하여 DOM 트리로 만들고 나면 각각의 태그에 접근하기가 한결 쉬워진다

또한 DOM 트리로 만들면 하위 태그를 추가하거나 데이터를 변경하는 것도 간단해진다

파싱 (구문 분석) 단계

문서를 파싱하는 과정은 크게 토크나이저 (Tokenizer), 렉서 (Lexer), 파서 (Parser) 세 단계로 나눠진다

토크나이저

어떤 구문에서 의미있는 요소 (XML을 예시로 들면, 태그) 들을 작은 토큰으로 쪼개는 역할을 한다

토큰으로 쪼개기 때문에 토크나이저… 라고 생각하니 쉽다

토큰의 단위는 문서의 형식에 따라 다르고, 위에 적었듯 의미있는 요소들을 토큰으로 쪼갠다

문장을 자른다면 단어, 단어구 단위로 자를 수도 있고, XML을 자른다면 태그 기준으로 자를 수도 있을 것이다

렉서

토크나이저를 통해 쪼갠 토큰에 의미를 부여한다

Tokenizer + Lexer를 합쳐 Lexical Analyze 라고도 하는데, 문서 내에서 의미 있는 문서 조각을 찾아내 토큰을 생성하는 것을 말한다

의미 있는 문서 조각이라 함은, 문장을 예로 들면 h, e, l, l, o 다섯 글자를 다 별개로 보면 별 의미가 없는 글자들로 보이지만 하나로 합쳐 hello로 만들면 비로소 의미를 갖게 되므로, 이것을 의미있는 문서 조각이라 할 수 있겠다

파서

Lexical Analyze 과정을 거친 토큰들을 가지고 구조적으로 표현한다

이 과정 속에서 데이터가 올바른지 검증 단계도 함께 거친다

  • 예를 들어, XML 파일이라면 태그가 잘 닫혔는지 검사할 것이다
  • 자바스크립트 등의 특정 언어라면, 문법을 잘 지켜 작성하는지 검사하고 아닐 경우 컴파일러는 소스 코드 구조화를 멈추고 에러를 반환한다

컴파일러에서 소스 코드를 구조화할 땐 AST (추상 구문 트리 - Abstract Syntax Tree) 구조를 많이 사용한다

추상 구문 트리

파일을 읽어들일 때 내용을 의미별로 구분하고, 이를 컴퓨터가 이해할 수 있는 구조로 변경한 트리를 의미한다

컴파일러가 작성하는 AST는, 프로그래밍 언어의 문법 (JS, TS, python, C 등…) 에 따라 소스 코드 구조를 표시하는 계층적 프로그램 표현이다

이 트리의 각 노드는 소스 코드에서의 항목 (item) 을 뜻한다

 

while (b !== 0) {
    if (a > b)
        a = a − b;
    else
        b = b − a;
}
return a;

위와 같은 코드가 있다고 해 보자

 

(사진과 코드는 위키피디아에서 발췌)

위의 코드에서 한 줄 한 줄의 모든 작업들을 트리 형태로 분리한 것을 볼 수 있다

트리의 맨 끝단 (마지막 노드, 자식노드가 없는 노드) 변수들이 들어갔고, 상위 노드에는 자식들을 이용하여 처리할 작업이 들어갔다

이처럼 코드의 내용을 트리로 만들면 프로그램을 실행시킬 때 컴퓨터가 어디서 어떤 작업을 행해야 하는지 알아들을 수 있다

이렇게 코드를 AST로 파싱하는 것은 컴파일러가 진행한다

파싱 단계에서 stack 활용하기

{{ 안녕하신가 } { 하이하이 }}

위와 같이 중괄호로 묶여있는 데이터를 생각해 보자

예시는 중괄호지만, XML에서는 태그가 될 수도 있다 아무튼 문서 내에서 열리고 닫히며 내부에 다른 요소를 포함하기만 하면 된다

여는 괄호의 개수를 세고 닫는 괄호의 개수를 세어야 하나? 복잡한 생각이 들 수도 있지만, 스택을 활용하면 이런 구조의 데이터를 쉽게 파싱할 수 있다

활용 방법

여는 괄호 또는 여는 태그를 만나면 스택에 push하고, 닫는 괄호 또는 닫는 태그를 만나면 스택의 가장 최신 값을 pop하는 방식으로 진행된다

  1. 문자열의 맨 앞에서 {를 만났으므로 스택에 push한다
    • 스택의 값: [ { ]
  2. 다음 문자열로 넘어가면, {를 만났으므로 스택에 push한다
    • 스택의 값: [ {, { ]
  3. ‘안녕하신가' 라는 문자열을 토큰화한다
  4. 다음 문자열로 넘어가면, }를 만났으므로 스택의 가장 최신 값을 pop한다
    • 보통은 닫는 괄호와 스택에서 pop하려는 괄호가 쌍이 맞는지 체크하고, 맞지 않다면 에러를 반환한다
    • 스택의 값: [ { ]
  5. 다음 문자열로 넘어가면, {를 만났으므로 스택에 push한다
    • 스택의 값: [ {, { ]
  6. ‘하이하이' 라는 문자열을 토큰화한다
  7. 다음 문자열로 넘어가면, }를 만났으므로 스택의 가장 최신 값을 pop한다
    • 스택의 값: [ { ]
  8. 다음 문자열로 넘어가면, }를 만났으므로 스택의 가장 최신 값을 pop한다
    • 스택의 값: [ ]

XPath

XML 문서의 노드나 노드셋을 선택하기 위한 문법

경로를 지정하면 해당 경로를 따라 노드를 선택하며, 추가적으로 속성이나 부모자식 관계 등을 명시하여 세부적인 선택이 가능하다

XPath는 XML 파일을 노드가 있는 트리로 만들어 생각하기 때문에, 부모나 자손 관계를 이용해서도 원하는 노드 (태그) 를 찾을 수 잇다

HTML 또한 XML의 일종이므로 XPath를 사용할 수 있다

XPath에서의 경로 표현

URL 경로를 통해 페이지를 탐색하듯 XPath도 / 구분자로 이어진 패스들을 톺아가며 원하는 노드를 찾을 수 있다

경로 표현은 두 종류가 있다

  • 절대경로
    • /부터 시작
    • 루트 노드 (최상위 노드) 부터 탐색해 나간다
  • 상대경로
    • /부터 시작하지 않음
    • 맨 처음에 지정되는 노드를 기준으로 탐색해 나간다

/ 왼쪽에 위치한 노드가 부모 노드, 오른쪽에 위치한 노드가 자식 노드이다

경로 표현 시 쓸 수 있는 추가 연산자

  • 경로연산자
    • /: 루트 노드부터 순서대로 탐색
    • //: 현재 노드의 위치와 상관없이 지정된 노드에서부터 순서대로 탐색
    • .: 현재 노드 선택
    • ..: 현재 노드의 부모 노드 선택
    • @: 속성 노드 선택 (class, href와 같은 attribute를 통해 노드를 선택할 때 사용한다
  • 검색 방향
    • self: 현재 노드 선택
    • attribute: 현재 노드의 속성 (attribute) 노드 선택
    • namespace: 현재 노드의 네임스페이스 노드 선택
    • child: 현재 노드의 자식 노드 모두 선택
    • descendent: 현재 노드의 자손 (자식, 손자, …) 노드 모두 선택
    • descendent-or-self: 현재 노드와 현재 노드의 자손 노드 모두 선택
    • following: 현재 노드의 종료 태그 이후에 등작하는 모든 노드 선택
    • following-sibling: 현재 노드 이후에 위치하는 형제 노드 모두 선택
    • parent: 현재 노드의 부모 노드 선택
    • ancestor: 현재 노드의 조상 노드 (부모, 조부모, …)모두 선택
    • ancestor-or-self: 현재 노드와 현재 노드의 조상 노드 모두 선택
    • preceding: 현재 노드 이전에 등장하는 모든 노드 선택
    • preceding: 현재 노드 이전에 위치하는 형제 노드 모두 선택
  • 경로 표현식
    • 검색방향::노드테스트[필터표현식] 방식으로 사용

참고 자료

텔넷웨어

코딩교육 티씨피스쿨

컴파일러 이론에서 토크나이저(Tokenizer), 렉서(Lexer), 파서(Parse) 의 역할

[컴파일러] 토크나이저, 렉서, 파서 (Tokenizer, Lexer, Parser)

추상 구문 트리 - 위키백과, 우리 모두의 백과사전

자바스크립트 개발자를 위한 AST(번역)

XPATH 사용법·작성법

코딩교육 티씨피스쿨

Comments