내장된 XPath 함수를 사용하세요

"Altova 온라인 교육 과정 중 하나를 개발하면서, 저는 책 목록을 저자별로 정리했습니다. 그러던 중, 제가 사용한 저자 정보 필드가 저자의 전체 이름으로 이루어진 문자열이라는 것을 깨달았습니다. 따라서 책들은 문자열의 첫 글자, 즉 저자의 성을 기준으로 정렬되었습니다. 이 정렬 방식을 수정하는 것은 해당 과정의 내용과 맞지 않았지만, XPath 함수를 사용하여 문자열에서 성을 쉽게 추출하고 이를 정렬 기준으로 사용할 수 있습니다. 만약 책 제목을 추가적인 정렬 기준으로 사용한다면, "A", "An", 또는 "The"로 시작하는 제목 때문에 문제가 발생할 수 있습니다. 저는 책 제목을 추가적인 정렬 기준으로 사용하고 싶지만, 맨 앞에 오는 부정관사나 정관사는 무시하고 싶습니다.

이번에는 이 XSLT 코드를 어떻게 만들었는지 살펴보겠습니다. 이 문서는 XMLSpy를 플랫폼으로 사용하여 작성되었지만, 동일한 XPath 표현식을 MapForce 또는 StyleVision 내에서도 사용하여 유사한 결과를 얻을 수 있습니다. 간단한 XML 형태의 도서 목록으로 시작해 보겠습니다. 여기에는 작가와 제목 노드를 가진 4권의 도서가 있습니다.

다음은 책 목록을 생성하는 XSLT 코드의 예시입니다

다음과 같은 결과가 생성됩니다

책들은 원본 데이터 파일에 나타나는 순서대로 출력됩니다. 만약 xsl:for-each 루프에 xsl:sort를 추가하면, 출력 결과를 다른 방식으로 정렬할 수 있습니다.

이렇게 하면 정렬된 목록이 생성되지만, 완벽하게 정렬되지는 않습니다.

저자는 문자열로 정렬되므로, "Jules Verne"가 "Mark Twain"보다 먼저 나타납니다. 또한, "A Connecticut Yankee in King Arthur’s Court"가 "Adventures of Huckleberry Finn"보다 먼저 나타납니다. 우리는 "A"와 같은 부정관사를 무시하여 "Adventures of Huckleberry Finn"가 "A Connecticut Yankee in King Arthur’s Court"보다 먼저 나타나도록 하고 싶습니다. 이를 위해 XPath 표현식을 사용하여 원하는 정렬 키를 추출할 수 있습니다.

출력 결과를 보기 전에 먼저 코드를 살펴보겠습니다. "author"를 "reverse(tokenize(author, ' '))[1]"로 대체합니다. tokenize 함수는 "author" 문자열을 공백을 기준으로 토큰으로 분리합니다. 따라서 "Jules Verne"은 "Jules"와 "Verne"로 분리됩니다. reverse 함수는 토큰의 순서를 뒤집어 "Verne"와 "Jules"가 됩니다. 대괄호 안의 숫자는 리스트에서 첫 번째 항목인 "Verne"을 선택합니다. 이 값은 xsl:sort 함수를 사용하여 책들을 정렬하는 데 사용됩니다. 완벽한 해결책은 아니지만, 이 경우에는 잘 작동합니다. 제목이 복잡해 보이지만, 그 논리는 간단합니다. "tokenize(title, ' ')[1]" 표현식은 제목의 첫 번째 단어를 추출합니다. 따라서 첫 번째 조건문은 "제목의 첫 번째 단어가 'A'인가?"입니다. 만약 그렇다면, 제목의 세 번째 문자부터 시작하는 부분 문자열을 반환하여 "A"와 공백을 제거합니다. 만약 제목의 첫 번째 단어가 "A"가 아니라면, 다시 조건을 확인하여 제목의 첫 번째 단어가 "The"인지 확인해야 합니다. 만약 그렇다면, 제목의 다섯 번째 문자부터 시작하는 부분 문자열을 사용하여 "The"와 공백을 제거합니다. 두 가지 조건 모두 만족하지 않으면, 제목을 그대로 정렬 키로 사용합니다. 코드에 다른 조건을 추가하여 제목의 첫 번째 단어가 "An"인지 확인할 수도 있지만, 이 데이터 세트에서는 필요하지 않습니다. 마지막 XSLT를 실행하면 다음과 같은 결과가 출력됩니다.

"마크 트웨인"이 현재 "줄스 베른"보다 앞에 위치합니다. "허클베리 핀의 모험"은 "캘러버라스 카운티의 유명한 뛰는 개구리"와 "아서 왕의 궁정에서 온 코네티컷 사람"보다 앞에 나타납니다. 저희가 작가 이름을 처리하는 방식의 문제점은 "줄스 베른"을 정렬 시 "베른, 줄스"로 취급하도록 설정하고 싶다는 것입니다. 따라서 "지미 베른"이라는 이름의 책이 있다면, 정렬 과정에서 이들을 서로 다른 작가로 인식해야 합니다. 하지만 현재 저희 코드는 그렇게 작동하지 않습니다. "concat(reverse(tokenize(author, ' '))[1], reverse(tokenize(author, ' '))[2])"를 사용하면 "줄스 베른"과 "지미 베른"을 올바르게 정렬할 수 있지만, 이 방법은 2단어 이름에만 적용됩니다. 만약 작가가 중간 이름이나 여러 단어로 이루어진 이름을 가지고 있다면 ("마틴 루터 킹 주니어", "조지 허버트 워커 부시" 등), 코드는 제대로 작동하지 않을 것입니다. 이름 정렬에 대한 일반적인 규칙에는 많은 예외가 있으며, 모든 변형을 처리할 수 있는 코드를 구현하는 것은 이 문서의 범위를 벗어납니다. 저희가 보여주고 싶었던 것은 XPath 표현식을 사용하여 XML 데이터를 실시간으로 조작하는 기능입니다. 저희는 항상 데이터 소스의 형식을 완벽하게 제어할 수 없지만, XPath 표현식의 강력한 기능을 활용하여 필요한 형식으로 데이터를 변환할 수 있습니다. 이 예제에 사용된 파일의 복사본은 여기에서 확인할 수 있습니다.