'XML'에 해당되는 글 3건

  1. 2009.02.02 XPath - attribute 값으로 특정 엘리먼트 찾기 (6)
  2. 2008.04.03 msxml 파서 사용하기 (2)
  3. 2007.10.04 XML 기초 (9)
동일한 엘리먼트 사이에서 특정 속성 값을 가진 엘리먼트만 찾고자 한다면 어떻게 해야 할까?
이래 저래 자료를 찾아 보다 귀찮아진 나는 자칭 xml 고수라 하는 Rhea君 에게 물어 보았다.

기대와는 달리 Rhea君의 대답은 절대 못한다 였다.
(사실..절대 라고까지는 하지 않았고...특정 케이스를 한정 지어 줬지만...어떻게든 깎아 내리고 싶은 내 맘을 알아 줬으면 좋겠다).

하.지.만 MSDN 문서(http://msdn.microsoft.com/en-us/library/ms256135.aspx)에는 분명히 attribute의 값을 이용해 특정 엘리먼트를 찾아 내는 방법이 있었다.

예를 들어 :
<element attr="name1"/>
<element attr="name2"/>
와 같은 xml 문서가 있다고 하자.

위의 element들 중에서 attr이 name1 인 경우만 찾고자 한다면 element[@attr = "name1"] 이라고 xpath를 적어 주면 된다.
(참고로 name1 옆에 따옴표는 꼭 써줘야 한다. 개인적으로 저 따옴표를 빼먹어 한참을 삽질한적이 있다)

보다 더 많은 설명은 http://msdn.microsoft.com/en-us/library/ms256135.aspx 를 참조하면 된다. 만일 링크가 깨졌다면 MSDN > Library tab > .NET Development > .NET Framework 3.5 > General Reference for the .NET > XML Standards Reference > XPath Reference > XPath Syntax > Comparison 에서 찾으면 된다(헥헥)

오늘의 교훈 :
  • Rhea君군은 거짓말쟁이!! 워우워우 베이베~!
  • 물어 보기 전에 문서를 먼저 더 자세히 찾아 보자.
 
Posted by kukuta
TAG XML, xpath

댓글을 달아 주세요

  1. Favicon of http://rhea.pe.kr/ BlogIcon Rhea君 2009.02.02 17:13  댓글주소  수정/삭제  댓글쓰기

    난 고수라고 한적음따!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    이런 썩은 감자! -_-;;;;;;;;

  2. Favicon of http://blog.ggamsso.wo.tc BlogIcon 깜쏘 2009.02.02 17:20  댓글주소  수정/삭제  댓글쓰기

    이게 뭡니까 -_-;;
    빅맥 내놔요.
    안 그럼 선배 미워할겁니다.

MSXML에 관한 VB나 C# 같은 언어의 예제는 많은데 C++의 예제는 별로 없는 것 같아 간단하게 나마 예제 코드를 만들어 봅니다. 코드를 보시기 전에 xml에 대한 기본적인 개념을 익히시고 싶으신 분은 XML 기초를 참조해 주세요.

MSXML API를 사용하기 위해서는 COM을 어느정도 알면 상당히 편하겠지만 몰라도 상관은 없습니다. 저도 COM에 관해서는 잘 모르기 때문에 이번 포스트에서 그와 관련된 설명은 건너 뛰기로 하겠습니다. 또한 MSXML 파서 설치 같은 것은 기본적으로 다 되어 있다고 가정하고 시작하도록 하겠습니다. 혹시나 설치나 설정 등에 어려움을 겪으신다면 댓글로 남겨 주세요. 그에 대한 포스팅을 따로 마련 해보도록 하겠습니다.
 
이 포스트는 MSXML4.0 버젼을 기준으로 작성 되었으며 포스트에서 예제로 사용하고 있는 xml파일은 첨부 파일로 저장되어 있으니 포스트를 읽어 보시기 전에 첨부 파일을 다운로드 받으시는 것이 전체적으로 이해 하시기 편할 것이라 생각 됩니다.



1. Dll import
MSXML 파서를 사용하기 위해서는 DLL을 import해야 합니다. 헤더 파일과 라이브러리를 로딩 하는 방법도 있지만 여기서는 dll을 import하는 방법을 사용하도록 하겠습니다. 우리가 사용하는 버젼은 msxml4.0 버젼이므로 아래와 같은 코드를 추가 합니다 :

#import <msxml4.dll>


2. 초기화
초기화 과정에는 COM객체를 사용하기 위한 초기화와 XML Document를 사용하기 위한 초기화 과정. 이렇게 두 단계가 있습니다. 물론 XML 파서가 COM을 사용하고 있으므로 COM에 대한 초기화가 먼저 이루어 져야 합니다 :

 // COM 객체를 사용하기 위해 초기화를 한다.
 // 윈도우 버젼 버젼이 올라가면서 확장된 초기화 함수를 사용 할 수 있다.
bool initializeCOM() {
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
    CoInitialize(NULL);
#endif
    return true;
}

COM객체를 사용할 준비를 마치고 나면 XMLDocument 객체를 초기화 해야 합니다. 여기서 사용되는 것XMLDOMDocument 인터페이스를 초기화 해야 합니다. 여기서는 편의상 IXMLDOMDocuement를 전역 변수로 놓도록 하겠습니다. 그리고 코드 작성의 편의를 위해 스마트 포인터로 정의 되어 있는 IXMLDOMDocument2Ptr을 사용하도록 하겠습니다 :

// DOM 의 핵심이 되는 객체
// 파싱된 XML을 저장하고 기타 각종 설정들을 담고 있다.

MSXML2::IXMLDOMDocument2Ptr g_pXMLDoc;
...
bool initializeMSXML() {
    g_pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
    g_pXMLDoc->async = VARIANT_FALSE;
    g_pXMLDoc->validateOnParse = VARIANT_TRUE;
    g_pXMLDoc->resolveExternals = VARIANT_TRUE;
    return true;
}

3. Validation check
MSXML파서의 기능중 하나는 xml파일의 정합성(validation)을 검증하는 것입니다. 여기서 정합성이란 단순한 well-formed 문서 뿐만 아니라, 스키마나 DTD에서 정의한 규칙을 제대로 따르고 있는가하는 것 까지 모두 검사하는 것입니다. 사용된 xml문서는 첨부 파일에서 다운 받으실 수 있습니다 :

bool validateDocument(const std::string& fileName) {
    g_pXMLDoc->load(fileName.c_str());

    // 최근 실행 된 XML관련 오퍼레이션에 대한 결과를 리턴
    MSXML2::IXMLDOMParseErrorPtr pError = g_pXMLDoc->parseError;

    _bstr_t strResult = "";
    bool isValidate = true;
    if (pError->errorCode != S_OK) {
        strResult = _bstr_t("Validation failed on ") + fileName.c_str() +
        _bstr_t("\n=====================") +
        _bstr_t("\nReason: ") + _bstr_t(pError->Getreason()) +
        _bstr_t("\nSource: ") + _bstr_t(pError->GetsrcText()) +
        _bstr_t("\nLine: ") + _bstr_t(pError->Getline()) +
        _bstr_t("\n");
        isValidate = false;
    }
    else {
        strResult = _bstr_t("Validation succeeded for ") + fileName.c_str() +
        _bstr_t("\n======================\n") +
        _bstr_t(g_pXMLDoc->xml) + _bstr_t("\n");
        isValidate = true;
    }

    pError.Release(); // RefCount를 사용하는 포인터이므로 Release과정이 꼭 필요

    std::cout << ConverseBstrToString(strResult) << std::endl;
    return isValidate;
}

4. _bstr_t를 char* 로 변환 하기
XML파서에서 리턴하는_bstr_t 라는 문자열을 일반 cout이나 printf에서 출력 하면 정상적인 문자열이 출력되는 것이 아니라 알 수 없는 숫자들의 나열로 출력이 됩니다. 이유인즉슨 wide char를 사용하는 xml과 아스키코드를 사용하는 C/C++간의 문자열 바이트 차이 때문인데요, 이 문자열들을 정상적으로 보기 위해서는 간단한 변환 과정을 거쳐야 합니다 :

#include <atlconv.h> // USES_CONVERSION과 W2A를 사용하기 위해 include
...
std::string ConverseBstrToString(const _bstr_t& str) {
    USES_CONVERSION;
    return std::string(W2A(str));
}

altconv.h 파일을 인클루드 하기 싫으시다면 아래의 방법도 있습니다 :

std::string ConverseBstrToString(const _bstr_t& str) {
    char buf[1024] = {0,};
    sprintf(buf, "%S", (LPCTSTR)str);
    return std::string(buf);
}

5. 엘리먼트의 텍스트 읽어 오기
첨부 되어 있는 예제 xml 문서를 보면 아래와 같은 형식의 comment 라는 엘리먼트가 있습니다 :

<purchaseOrder ... >
    ....
    <comment>Hurry, my lawn is going wild!</comment>
    ....
</purchaseOrder>

위의 comment가 가지고 있는 텍스트를 읽어오기 위해서는 먼저 comment의 엘리먼트를 얻어오고, 그 엘리먼트에서 텍스트를 가지고 오면 됩니다 :

void selectSingleElement_and_getText() {
    MSXML2::IXMLDOMNodePtr singleNodePtr = g_pXMLDoc->selectSingleNode(_bstr_t("/purchaseOrder/comment"));
    if(NULL == singleNodePtr) {
        return;
    }
    const BSTR str = singleNodePtr->Gettext();
    std::cout << ConverseBstrToString(str) << std::endl;

    singleNodePtr.Release();
}

코드 자체가 워낙 간단하여 긴 설명 보다는 개조식의 간단한 설명을 드리겠습니다 :

  1. 엘리먼트를 저장하기 위해서 IXMLDOMNodePtr을 선언 합니다.
  2. XMLDocument객체에서 selectSingleNode를 이용해 엘리먼트 객체를 얻어 옵니다. 이 때 XPath를 이용합니다.
    (이 함수는 특정 하나의 엘리먼트를 얻어오기 위해 사용되는 것입니다. 엘리먼트 리스트를 얻어오기 위한 함수는 뒤에서 다시 한번 살펴 보기로 하겠습니다.)
  3. 얻어진 엘리먼트에서 Gettext()를 호출 하여 텍스트 내용을 얻어 옵니다.
  4. 얻어진 텍스트를 아스키 형태로 변환하기 위해 위에서 작성한 ConverseBstrToString() 함수를 이용 합니다.

6. 엘리먼트의 속성(attribute) 읽어 오기

void selectSingleElement_and_getAttribute() {
    MSXML2::IXMLDOMNodePtr singleNodePtr;
    MSXML2::IXMLDOMAttributePtr attrPtr;
    std::string retString("");

    do {
        singleNodePtr = g_pXMLDoc->selectSingleNode(_bstr_t("/purchaseOrder/shipTo"));
        if(NULL == singleNodePtr) {
            break;
        }
        attrPtr = singleNodePtr->Getattributes()->getNamedItem("country");
        if(NULL == attrPtr) {
            break;
        }
        const BSTR str = attrPtr->Getvalue().bstrVal;
        // or 'const BSTR str = attrPtr->Gettext() is ok'
        retString = ConverseBstrToString(str);
    } while(false);

    if(NULL != singleNodePtr) {
        singleNodePtr.Release();
    }
    if(NULL != attrPtr) {
        attrPtr.Release();
    }

    std::cout << "Attribute in Element : " << retString << std::endl;
}
  1. selectSingleNode() 함수를 이용하여 엘리먼트를 얻어 오는 것 까지는 위에서 살펴 본 것과 동일합니다.
  2. 엘리먼트를 얻고 난 후에는 Getattributes() 함수를 이용해 어트리뷰트들을 얻고, getNamedItem() 함수를 이용해 특정 어트리뷰트를 이름을 통해 가지고 옵니다.
  3. 어트리뷰트가 가지고 있는 값을 가지고 올 때, 어트리뷰트의 타입을 지정할 수 있습니다. 만일 어트리뷰트가 단순한 문자열이라면 Getvalue().bstrVal 이나 Gettext() 함수를 이용해 가지고 올 수 있습니다. 만일 정수라던지 하는 다른 타입일 경우 Getvalue().xxxVal에서 적절한 타입을 지정해 주시면 됩니다. 지정될 타입에 대해서는 MSDN이나 해당 union 구조체를 확인 하시면 됩니다.

7. 엘리먼트 리스트 읽어 오기

엘리먼트 리스트에서 값을 얻어 오는 것 또한 위의 과정들과 크게 다르지 않습니다 :

void selectElementArray() {
    MSXML2::IXMLDOMNodeListPtr nodeListPtr = g_pXMLDoc->selectNodes(_bstr_t("/purchaseOrder/items/item"));
    for(int i=0; i<nodeListPtr->Getlength(); i++) {
        MSXML2::IXMLDOMNodePtr parentNodePtr = nodeListPtr->Getitem(i);
        MSXML2::IXMLDOMNodePtr childNodePtr = parentNodePtr->selectSingleNode(_bstr_t("productName"));
        if(NULL != childNodePtr) {
            const BSTR str = childNodePtr->Gettext();
            std::cout << util::ConverseBstrToString(str) << std::endl;
        }
        childNodePtr.Release();
        parentNodePtr.Release();

    }
    nodeListPtr.Release();
}
  1. 가장 먼저 하는 일은 selectNodes() 함수를 이용해 엘리먼트 리스트를 얻어 오는 것입니다.
  2. 엘리먼트 리스트를 얻어 오는 것이 성공하면 IXMLDOMNodeListPtr에 그 값이 저장 됩니다. 만일 엘리먼트가 하나 뿐이거나 기타등등 조건에 맞지 않는 경우 NULL을 리턴하므로 다른 함수도 물론 그렇지만 이 함수를 호출 하고난 후에 NULL체크를 하여 성공 여부를 판단하는 것이 중요 합니다.
  3. 몇 개의 엘리먼트를 얻어 왔는지는 Getlength() 함수를 통해 알아 낼 수 있습니다.
  4. 엘리먼트 리스트는 인덱스를 지정하므로써 각각의 엘리먼트들에게 접근 할 수 있습니다. 이 때 사용되는 함수는 Getitem()이며 파라메터로 인덱스를 받습니다.
  5. 그 외의 나머지 과정의 위에서 설명한 과정과 동일 합니다.
결론
간단하게 나마 msxml 파서의 사용법에 대해서 알아 보았습니다. msxml에 대해서 정확하게 알아 보기 위해서는 DOM과 COM 스펙에 대해 좀 더 조사하고, 위에 언급한 API말고도 수많은 편리함을 제공 해 주는 API들이 많지만 필자가 공부를 하면서 가장 많이 사용했던 API 몇 가지에 대해서만 언급을 하였습니다. 보다 더 많은 정보가 필요하신 분들은 MSDN이나 W3C에 방문하셔서 검색해 보시면 심도 있는 정보를 얻으실 수 있으실 겁니다.


Ref.

'도구의발견' 카테고리의 다른 글

SVN 사용하기  (0) 2008.04.30
memcached  (0) 2008.04.19
msxml 파서 사용하기  (2) 2008.04.03
Dependency Walker 2.2  (0) 2008.03.21
Shell 프롬프트에서의 단축키  (0) 2008.03.11
putty 한글 사용하기  (0) 2008.02.20
Posted by kukuta
TAG C/C++, XML

댓글을 달아 주세요

  1. Favicon of http://blog.naver.com/cor2738 BlogIcon graphire 2011.06.09 21:58  댓글주소  수정/삭제  댓글쓰기

    좋은 정보 감사합니다. 담아갈께요

  2. sch 2011.07.02 17:13  댓글주소  수정/삭제  댓글쓰기

    큰 도움 되었습니다. 많이 알았습니다

XML 기초

진리는어디에 2007.10.04 15:45
이번 포스트의 "XML의 의미"라고 적은 것은 XML의 기본적인 개념과 기능들을 알아 보고 XML이라는 도구를 어떻게 우리 생활에 도움이 되도록 사용 할 수 있는지 알아 보고자 함이다. 책이나 기타 웹문서에도 XML에 대한 설명들이 잘 나와 있지만, 여기에는 XML을 공부하면서 개인적으로 느꼈던 XML의 특성과 장점을 들어 어떻게 우리 생활에 XML이라는 도구가 도움을 줄 수 있는지 알아 보고자 한다.

XML 기능
 XML이 어떻게 우리 생활에 도움이 되는지 알아보기 전에 XML이 할 수 있는 일에 대해서 먼저 알아 보도록 하자. 흔히 우리는 XML이라고 하여 간단한 태깅 기능을 제공하는 문서만을 생각하지만 개인적으로는 XML, XPath, XSTL, Schema or DTD들을 묶은 하나의 패키지 형태가 XML의 진정한 모습이 아닐까 생각한다. 이제 부터 나오는 'XML 패키지'라는 단어는 XML, XPath, XSTL, Schema들을 통칭하는 단어라고 알아 두자. 일단 XML 패키지 각자의 기능들에 대해 살펴 보도록 하자.
 
XML
XML은 기본적인 태그 기능을 제공하며, 데이터의 문서화가 그 주된 목적이라고 생각된다. 태깅을 통하여 구조화된 데이터의 표현이 가능하다. 예를 들어 일반 텍스트 문서에서 address라는 데이터 형식을 표현 하고자하고, 또 그 address는 country, state, city, street, zip code라는 요소들을 가져야 한다면 아마도 아래 처럼 표시될 것이다 :
name="Allice Smith"
country="US"
state="CA"
city="Mill Valley"
street="123 Maple Street"
zip="90952"

name="Robert Smith"
country="US"
state="PA"
city="Old Town"
street="8 Oak Avenue"
zip="3393"

위의 예제의 데이터들 사이에서는 연관성을 찾아보기가 힘들 뿐더러, 데이터의 사용자가 데이터의 관계를 미리 알고 있지 않다면 제대로 이해하기 힘든 형태다(사실..이렇게 간단하게 표현된 형식은 누가 봐도 이해가 가능 하지만, 실질적으로 문서 자체에서 데이터의 연관 관계에 대해 표시하고 있는 부분은 없다).

XML은 이런 데이터에 계층성을 부여하여 데이터를 구조화 시키고, 데이터 표현 자체가 하나의 문서가 되도록 할 수 있는 기능을 제공한다. 아래의 예를 계속 살펴 보도록 하자 :
<address name="Alice Smith">
        <country>US</country>
        <street>123 Maple Street</street>
        <city>Mill Valley</city>
        <state>CA</state>
        <zip>90952</zip>
</address>
<address name="Robert Smith">
        <country>US</country>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>3393</zip>
</address>
첫번째 예제 보다는 훨씬 알아 보기 쉬운 형태다(적어도 나는 그렇게 생각한다). address라는 하위 개념에 country나 street라는 하위 요소들이 포함 되어 있는 것이 확연히 보이고, 하위 요소에서도 어떤 상위 요소에 속해 있는 것인지 명확하다. 그리고 시작 태그와 종료 태그의 표시로써 어디가 데이터 표현의 시작이고 끝인지가 보다 명확해 지고 있다.

 * XML은 데이터를 계층적으로 구조화 시킬 수 있게 한다.
 * XML은 데이터 자체를 문서로 표현 할 수 있게 한다.
 * XML은 간단한 문법 체킹 기능을 제공해 well-formed(시작 태그와 종료 태그가 잘 정의된) 문서인지 아닌지를 판별 해 준다.

Schema
 Schema라는 XML문서의 문법을 정의 하는 XML 문서라 할 수 있다. XML 문서에서 나타나는 요소(element)와 속성(attribute)들의 순서와 포함 관계, 필수적으로 사용되어야만 하는 것인지 선택적으로 사용이 가능한 것인지, 사용된다면 최대로 문서내에서 사용될 수 있는 횟수와 최소 몇 번은 사용되어야 하는지 등을 나타낼 수 있는 제약 사항을 표현 할 수 있는 독특한 형식의 xml 문서라 할 수 있겠다.

 예를 들어 위의 예에서 사용되었던 address라는 요소를 생각한다면, 주소라는 개념 안에는 country, state, city, street가 필수 적으로 들어 가야만 하면 위의 요소들은 한 번만 address 요소 안에서 표시되어야지 그 이상은 안된다. 그리고 zip 코드는 일반적으로 사용되면 좋고 사용하지 않아도 그렇게 배달이나 기타 주소를 알아보는데 있어서 문제가 되지는 않는다. 만일 이런 제약 사항이 지켜지지 않을 경우에는 적절한 오류를 사용자에게 보여주어야만 한다. XML 자체에는 이런 기능을 제공해 주지 않으므로 이런 기능을 돕기 위해 schema가 등장 하였다.

 Schema를 정의 하는 요소(element)들의 정의는 MSXML 그것과 W3C의 그것이 다소 다르다. 최초에는 MSXML schema가 보다 강력한 기능을 지원하고 있었고, W3C에서는 확실히 이것이다 라고 하는 표준이 없었다고 한다. 하지만 그 이후 W3C에서 표준으로 정의된 1.0 버젼이 나왔고, MSXML 4.0버젼 부터는 MS에서도 W3C의 schema 를 지원 하기 시작 했다고 한다. 현재 MSDN을 찾아 봐도 MSXML schema 보다는 W3C형식의 schema 문법을 주로 보여 주고 있다.

 MSXML에서는 schema 문서의 확장자 역시 .xml이었으나, 현재는 W3C의 .xsd라는 확장자를 따르고 있다.

 Schema의 자세한 사용방법은 MSDN이나 W3C의 문서등 좋은 자료가 많이 있고, 주변에 나 보다 더 설명을 잘하는 책들이 널려 있으니 간단한 개념(내가 공부하면서 아리송했던 것들 위주)만 설명 하고 넘어 가도록 하겠다.

 먼저 schema의 간단한 예를 보도록 하자.
1: <?xml version="1.0" encoding="utf-8" ?>
2: <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3:   <xs:element name="address" type="addressType"></xs:element>
4:   <xs:complexType name="addressType">
5:      <xs:sequence>
6:        <xs:element name="country" type="xs:string" maxOccurs="1"/>
7:        <xs:element name="state" type="xs:string" maxOccurs="1"/>
8:        <xs:element name="city" type="xs:string" maxOccurs="1"/>
9:        <xs:element name="street" type="xs:string" maxOccurs="1"/>
10:      <xs:element name="zip" type="xs:integer" minOccurs="0" maxOccurs="1"/>
11:     </xs:sequence>
12:   </xs:complexType>
13: </xs:schema>
 line 2를 보면 Schema 문서를 정의하기 위해서 schema라는 root element를 사용하고 있다. 이 요소에 대한 정의는 "http://www.w3.org/2001/XMLSchema" namespace에 있으며, 통상적으로 스키마 요소를 정의하고 있는 namespace는 xsd라고 한다. 다른 프로그래머들이 볼때에도 일관성 있는 가독성을 제공하기 위해 xsd namespace를 사용하는 것이 권고안이다(하지만 VS2003에서 자동적으로 schema를 생성하면 xs라는 namespace로 설정된다).

 line 3은 사용되는 element를 표시하기 위해서 element라는 요소를 사용한다. type에 string, integer등의 기본 데이터 형이 들어 갈 수도 있고 사용자가 직접 정의한 데이터 형이 들어 갈 수도 있다.

 line 4~12까지 complex type에 대한 정의를 하고 있는데, W3C에서는 새로운 데이터 타입을 정의하기 위해 complexType과 simpleType 두 가지 형태를 제공하고 있다. complexType은 말 그대로 복잡한 데이터형, 자식 요소들을 가지고 있고 attribute가 있는 형태의 데이터 형을 정의 할 때 사용되고, simpleType은 요소 하나에 계층 구조 등의 복잡한 구조가 필요 하지 않을 때 사용된다.

 나머지 보다 자세한 설명은 얇고 넓은 지식을 전파 하려는 이 포스트의 목적에 어긋나므로 자세한 설명은 다른 인터넷 문서나 책들에게 미루겠다(게으르니즘, 귀차니즘..).
 http://msdn2.microsoft.com/en-us/library/ms256142.aspx
 혹시나 링크가 깨져 있을 경우에는 MSDN 검색 창에서 "xml schema"라고 검색하면 원하는 정보를 얻을 것이다.

 XML문서에서 schema를 사용하는 방법은 다양한 방법이 있으나 일반적으로 noNamespaceSchemaLocation를 사용한다. 보다 자세한 내용과 다른 방식의 참조는 Referencing XSD Schemas in Documents(http://msdn2.microsoft.com/en-us/library/ms757863.aspx)를 참조 하도록 한다.

noNamesapceSchemaLocation 사용  
 XML문서 내에서 schema를 사용하는 요소들이 namespace를 사용하지 않는 경우 사용.
1: <z:catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:z=" www.microsoft.com/zzz">
2:    <book xsi:noNamespaceSchemaLocation="http://www.example.com/MyData.xsd" id="bk101">
3:       <title>Presenting XML</title>
4:       <author>Richard Light</author>
5:    </book>
6: </z:catalog>

 line 1을 보면 noNamespaceSchemaLocation을 사용하기 위해서 http://www.w3.org/2001/XMLSchema-instance URI로 namespace를 선언하는 것이 보인다. 일반적으로 XMLSchema instance의 namespace는 xsi라고 사용한다. 일관성과 가독성을 위해 xsi를 사용하는 것이 권고안이다.
 
  line 2에는 noNameSpaceSchemaLocation을 이용해서 schema파일에 접근하고 있다. 만일 MyData.xsd가 웹상에서 접근이 가능하다면 namespace가 prefix되지 않은 book과 그 자식 노드들에 대해서 validate을 할 것이다. 만일 로컬에 사용하고자 하면 file-system URL을 대신 사용하면 된다. 스키마 파일과 xml문서가 같은 디렉토리에 있다면 단순히 파일이름만 적어 줘도 된다.

 만일 Mydata.xsd가 valid하지 않은 xml문서라면 msxml은 schema에 관련한 것은 무시하고 단지 well-formed인지 아닌지만 판단한다. 이런 결과를 방지하기 위해서는 schema파일은 항상 먼저 validation check하는 습관을 기르는 것이 좋다.

 * Schema는 xml의 문서에 기록되어 있는 데이터 포멧에 대한 유효성을 검증하는 기능을 제공한다.
 * Schema의 확장자는  .xsd를 가진다.
 * Element의 순서, 갯수, 계층 구조에 대한 포괄적인 제약사항을 기술 할 수 있다.
 * schema라는 root element로 시작 해야 한다.
 * 일반 문서에서 schema를 참조하는 방식은 여러가지가 있다. 그 중 noNamespaceSchemaLocation에 대한 내용이 이 포스트에 소개 되었다.
 * Schema 문서 자체가 잘 못되었을 경우, schema의 제약사항들을 무시하고 단순히 well-formed만 검사한다.

XPath
 XML은 의미가 부여된 태그를 사용하여 다양하고 효율적인 데이터 표현 수단이다. 하지만 XML은 주어진 문서 안에서 구조화된 데이터의 특정 부분을 가리키는 수단은 제공하지 않는다. XPath는 효율적으로 XML의 특정 부분에 대한 접근을 가능하게 하는 방법을 제공한다.

 개념적으로 XPath 에서는 XML문서의 각 부분(element, attribute 등)을 노드로 표현되는 트리로 간주한다. 이는 컴퓨터 하드드라이브의 디렉토리 구조와 아주 흡사하다.

 XPath 는 7개 형태의 노드 타입을 갖는다. root, element, attribute, text, comment, PI(Process Instruction), namespace이다. XPath 트리는 트리 상의 다른 모든 노드를 포함하는 root node를 가지고 있다. root node를 제외한 모든 노드는 부모 노드를 가지며, 부모 노드는 임의의 개수의 자식 노드들을 가질 수 있다.

  • PI (Processing Instruction)
    XML 문서를 처리 하는 방법에 대해서 제시. 버젼과 인코딩 방법들을 기술 할 수 있다.
  • Root
    Element의 형태를 띄고 있지만 Element와는 특성이 다소 다르다. Element는 한 문서안에 어려번에 걸쳐서 나타날 수 있지만 Root는 딱 한번만 나타날 수 있으며, 모든 element와 attribute등은 이 root안에 기술 되어져야만 한다.
  • Element
    하나의 사용자 저의 '태그'라고 이해 할 수 있다. 항상 시작을 하는 element가 있으면 닫아주는 element가 있어야 하며, element안에 element가 추가 될 수있으며 재귀적인 기술도 가능하다.
  • Attribute
    Element의 내부에서 element의 특성을 기술한다.
  • Text
    Element의 시작태그와 끝을 내는 닫는 태그 사이에 기술 될 수 있으며 일반문자열 그대로 해석된다.
  • Comment
    XML파서에 의해 해석되지 않으며 단지 사용자의 가독성을 돕기 위해 기술된다.
  • Namespace
 XPath가 특정 노드(element or attribute)에 접근하는 방법은 일반적인 directory path notation와 아주 흡사하게 사용한다. 예를 들어 root element를 참조하기 위해서는 '/'를 사용한다. address를 표현한 XML문서에서 state를 참조하기 위해서는 "address/state"를 사용하면 된다. 만일 address element의 attribute인 name을 참조하기 위해서는 "address/@name"을 사용한다. 보다 자세한 내용은 'Context for XPath Expression(http://msdn2.microsoft.com/en-us/library/ms256199.aspx)'를 참조하도록 한다.
 
 * XPath는 XML 문서 내에서 특정 요소에 다이렉트로 접근하는 방법을 제공한다.
 * XPath는 XML 문서가 아니다.
 * XPath는 디렉토리 path notation과 아주 흡사한 notation을 제공한다.

XSLT(Extensible Stylesheet Language for Transformation)
XSTL은 확장 가능한 stylesheet language로써 XML문서를 여러가지 다른 포멧으로 변경 시키는 기능을 한다. 좀 더 원론적으로 말하자면 하나의 데이터를 가지고 여러 형태로 보여줄수 있는 기능을 제공한다. XML문서를 PDF 포멧을 변경시켜서 보여 줄수도 있고, HTML, C++ code등의 여러가지 문서로 변형이 가능하다. XSLT은 XML 문서를 사용자가 정의한 transform rule에 따라 변형시켜 보여주는 기능을 가지고 있다.

Schema가 xsd 확장자를 사용한다면 XSLT은 .xsl 확장자를 사용한다. 아래의 예제를 보도록 하자 :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  ...  
  <body bgcolor="white">
   <h1>Purchase Order Date : <xsl:value-of select="@orderDate"/></h1>
   <h2>Ship to</h2>
   <table border="1">
    <tr>
     <td>Country</td><td><xsl:value-of select="shipTo/@country"/></td>
    </tr>
    ...
   </table>
   ...
   <xsl:value-of select="comment"/>
   <table border="1">
    <xsl:for-each select="items/item">
     <xsl:sort select="@partNum" order="ascending"/>
     <tr>
      <td><xsl:value-of select="productName"/></td>
       ...
      </tr>
    </xsl:for-each>
   </table>
  </body>
 </xsl:template>
</xsl:stylesheet>

포스트가 너무 길어지는 감이 있어 많은 부분을 생략했다. 전체 문서를 보고 싶다면 첨부 파일을 참조 하도록 한다. XSTL 문서를 작성하기 위해서 "http://www.w3.org/1999/XSL/Transform" namespace를 사용하고 있다. 일반적으로 XSLT을 위해서 사용하는 namespace는 'xsl'이라고 칭한다. XSTL문서의 root element는 'xsl:stylesheet'가 되어야 한다. 제공되는 element로써는 element의 값을 참조하는 value-of, 동일한 이름을 가지는 element를 순회하면서 참조 할 수 있는 for-each, for-each등으로 얻어온 element list를 sort 할 수 있는 sort등이 있다. 또한 특정 element, attribute에 접근하기 위해서 위에서 살펴본 XPath를 이용하고 있다. 보다 자세한 설명은 "XSLT Element(http://msdn2.microsoft.com/en-us/library/ms256058.aspx)"를 참조 하도록한다.
  • XSLT은 사용자가 정의한 룰에 맞추어 XML 문서를 다른 포멧으로 변형 시켜주는 도구다.
  • XSTL은 특정 노드(elemnet, attribute)에 접근하여 값을 얻어오기 위해 XPath를 사용한다.
요약.
일반적으로 MVC패턴이라고 하여 데이터와 로직과 뷰를 따로 관리하는 패턴이 기능의 추가나 유지 보수에 좋다고 한다. 그런면에 있어서 XML은 상당히 유용하고 강력한 도구라고 생각한다.

예를들어서 XML로 어플리케이션의 인터페이스를 작성한다고 가정하자. Schema를 정의하는 것으로 다른 프로그래밍이 필요 없이 문서의 유효성을 검증 할 수 있다. 이렇게 유효성을 통과하는 문서에 대해서 XSLT을 이용하여 별다른 프로그램이 없이 C++, JAVA, PHP코드로 변환이 가능하다. 그리고 그 인터페이스를 설명하는 문서를 HTML이든 doc 문서든 어떠한 형태로 뽑아 내는 것이 가능하다. 코드가 문서가 되는 것의 반대인 문서가 코드로 표현 되는 개념이다.

다른 예를 들면, XML로 표현되어 있는 데이터들이 있다고 가정하자. 물론 schema를 통해서 문서 포멧에 대한 유효성은 검증 되었다고 하자. 이 데이터들을 DB에 넣고자 한다. 아니면 HTML을 이용해서 Web에서 바로 볼 수 있는 데이터 형으로 변경코자 한다라고 가정하자. XML은 데이터와 뷰가 분리되어 있으므로 얼마든지 데이터에 대한 수정 없이(그리고 새로운 뷰를 추가하는것도 그렇게 어렵지 않게) 다양한 뷰의 제공이 가능하다.   
  • XML은 문서를 표현하는 하나의 표현 방식이다.
  • XML은 데이터들을 계층적으로 표현하여 표현 자체가 하나의 문서가 될 수 있다.
  • XML은 schema나 DTD를 이용해서 문서내에 저장하는 데이터들의 형식과 제약 사항들을 정의 할 수 있고, 문서의 포멧에 대한 검증이 가능하다.
  • XML은 XSLT를 이용해서 동일 데이터를 여러가지 형태로 표현하는 것이 가능하다.
  • XML에 저장된 데이터는 XPath를 통해 다이렉트로 접근이 가능하다.
  • XML은 언어 자체적으로 로직, 데이터, 뷰를 따로 관리 하는 기능을 제공한다.
ref.
 네이버 사전 : http://100.naver.com/100.nhn?docid=717479
 위키피데아 : http://en.wikipedia.org/wiki/Xml

첨부 파일 :
 Test_msXml.xml, Test_msXml.xsd, Test_msXml.xsl
 VC2003 project(validation 검증을 위한 코드)


'진리는어디에' 카테고리의 다른 글

Composite Pattern  (2) 2007.10.23
RST 메시지  (0) 2007.10.10
XML 기초  (9) 2007.10.04
정규 표현식(Regular Expressions)  (0) 2007.08.31
커널 오브젝트 - 핸들  (0) 2007.07.23
connected UDP socket  (0) 2007.05.14
Posted by kukuta
TAG XML

댓글을 달아 주세요

  1. 김동진 2008.08.25 15:20  댓글주소  수정/삭제  댓글쓰기

    xml에 대한 좋은 자료 잘 보고 갑니다.
    수고하세요.

  2. 김판습 2008.12.23 10:42  댓글주소  수정/삭제  댓글쓰기

    자료를 찾아보다가 블로그에 들르게 되었습니다. 유용한 자료가 많아서 여러 글 많이 보고 갑니다. 수고하세요~

  3. Favicon of http://microdev.tistory.com BlogIcon 유근호 2009.04.28 14:45  댓글주소  수정/삭제  댓글쓰기

    스키마에 대한 자료를 찾던중 기초에 대해 잘 정리해주셔서 다시 한번 큰 도움이 되었습니다.^^

    쿠쿠타님 허락없이 제 블로그에 퍼갔는데(출처는 표시했음;;) 문제가 되신다면 글 남겨 주세요

    수고하세요~!!

    • Favicon of http://kukuta.tistory.com BlogIcon kukuta 2009.05.01 01:02  댓글주소  수정/삭제

      도움이 되셨다니 기쁩니다.

      같이 공부하자고 끄적거린 글이니까 얼마든지 퍼가셔도 괜찮습니다.

  4. 최재우 2009.05.01 12:12  댓글주소  수정/삭제  댓글쓰기

    xml에 대해서 완전 문외한이었는데..잘 보고 갑니다....정말 이해가 잘 되네요...

    유용한 자료들이 많은거 같아서 즐겨찾기 추가 했어요~

    요즘 공부하면서 좌절을 맛보고 있지만...열심히 하면 쿠쿠타님처럼 고수가 될수 있겠죠...ㅋㅋ

  5. Favicon of http://blog.naver.com/moya800 BlogIcon 마기의근원 2009.11.10 21:31  댓글주소  수정/삭제  댓글쓰기

    많이 배우고 갑니다 ^^