#ifdef WIN32
#define TRACE(fmt, ... ) Func( fmt, __VA_ARGS__ )
#else
#define TRACE(fmt, args...) Func( fmt, ##args )
#endif
TinyXML Download : http://sourceforge.net/projects/tinyxml/

09년 9월 8일 기준으로 2.5.3 버전으로 올라가있음.

파일 압축을 푼 후
tinystr.cpp
tinystr.h
tinyxml.cpp
tinyxml.h
tinyxmlerror.cpp
tinyxmlparser.cpp
파일들만 프로젝트에 추가.

그리고 tinyxml.h 만 인쿠르드 시키면 준비는 끝.

how to use.

TiXmlDocument g_doc;            // tinyxml 객체 변수 선언
g_doc.LoadFile( "파일명.xml" );

//또는
//TiXmlDocument g_doc( "파일명.xml" );
//g_doc.LoadFile();

TiXmlElement* pRoot = g_doc.RootElement();        // 루트 포인터 가져오기

//TiXmlNode* pNode = g_doc.FirstChild();
// 이 함수는 바로 아래 Child를 가져오는 함수인데. 어디든 바로 FirstChild() 호출하면
// 바로 다음 sibling 노드의 위치가 리턴된다. 단, LoadFile이후에 FirstChild()를 호출하게 되면
// 루트 엘리먼트가 아닌 <?xml version = ... >의 주소가 리턴되니 제일 처음엔
// 노드 이름을 알고 있어서 FirstChild( "노드명" )을 해주던가 root에서 FirstChild()를 호출하는 방법으로
// 시작하자.

<?xml version = 1.0 >
<root>
         <node>
                     text
          </node>
          <node2></node2>
</root>

<root> = RootElement(); 또는 FirstChild( "root" );
<node> = RootElement()->FirstChild(); 또는 FirstChild( "root" )->FirstChild();
<node2> = RootElement()->FirstChild("node2"); 또는 FirstChild( "root" )->FirstChild("node2");
                또는 RootElement()->sibling(); 등.. 접근 방법은 무궁무진
text = RootElement()->FirstChild()->ToElement()->GetText(); 주의할점은 FirstChild까지는 Node인데 ToElement부터는 Element로 포인트가 변경된다. GetText는 const char* 형 리턴.
 * TiXmlBase <- TiXmlNode <- TiXmlElement 의 상속구조.
 * 노드의 이름은 대소문자를 구별함. 잘 못 표기할 경우 NULL을 리턴하므로 주의.

RootElement()->FirstChild()->Value(); 하면 "node" 가 리턴됨

TiXmlHandle 이라는 녀석이 있는데, 아직은 잘 모르겠다.
핸들을 쓰게 되면 바뀌는 부분이 있는데 노드의 엘리먼트 값을 읽어올 때 이다.

const char* pText1 = RootElement()->FirstChild( "node" )->ToElement()->GetText();

TiXmlHandle hXml = RootElement()->FirstChild( "node" );
const char* pText2 = hXml.Element()->GetText();

두개 별 차이는 없어 보인다. 길게 들어간 노드의 주소를 일일이 타이핑 할 필요없이 핸들에 맡긴다던가 해서
타이핑을 줄이는 용도일라나? 아직은 잘 모르겠다.

이제 Attribute에 대한 부분 설명.
우선 엘리멘트 단까지 내려온다.
TiXmlNode* pNode = RootElement()->FirstChild( "test" )->FirstChild( "test2" );
TiXmlElement* pElement = pNode->ToElement();
// 만약 TiXmlNode가 아니고 TiXmlHandle로 받아왔다면 엘리먼트를 받아올때
// pNode->ToElement() 가 아니고 hXml.Element()이다. 주의.

//전략
<node name="test" index="99">테스트입니다.</node>
//후략

//Attribute용 변수 선언.
TiXmlAttribute* pAtt1 = pElement->FirstAttribute();
TiXmlAttribute* pAtt2 = pAtt->Next();

pAtt1->Value(); 를 호출하면 test 문자열을 뱉어낸다.
pAtt2->Value(); 는 99 ( 문자열이다. IntValue 나 DoubleValue가 있지만 안정성을 위해 문자열로 받아서
atoi 나 atof 로 변환해주는 방법을 쓰는건 어떨까 한다.)
참고로, pElement->Value() 는 node 이다.

만약, 특정 Attribute값을 가져오고 싶으면 함수 인자로 써주면 된다.
const char* pText = pElement->Attribute( "name" );
int index;
pElement->Attrib( "index", &index );
// 숫자나 실수형일 경우 위에 같이 함수인자로 사용해도 된다.

한방에 Element 까지 받아오는 방법.
지금까지는 노드 쭉 타고 가다가 ToElement()란 함수를 써서 엘리먼트의 주소를 가져왔지만
TiXmlElemnt* pElement = RootElement()->FirstChildElement( "찾을 엘리먼트의 노드명" );
이렇게 하면 한방에 엘리먼트~

마지막으로 정리.
XML 에서 Root는 언제나 단 한개뿐. 2진트리에서 꼭대기로 보면 됨.
Node란 Root에서 뻗어나간 2진트리의 각 지점을 노드라 부름.
Element란 노드를 구성하는 값들을 말하는 것 같음. 아직 명확한 정의가 잡히지 않았음.
Attribute란 엘리먼트의 값.

파라메터(parameter) : 파라메터는 함수에서 정의한 인자를 의미한다.

예 >
void swap( int a, int b );   // 여기서 a, b는 파라메터 이다.

아규먼트(argument) : 아규먼트는 함수에 넘겨줄 변수나 값을 의미한다.

예 >
int x, y;
x = 10;
y = 20;
swap( x, y );  // 여기서 x, y는 아규먼트가 된다.

/*      이 녀석이 하는 짓      */

어떠한 함수로 인자들의 값을 넘겨주는것 같음.
정확히 어디서 쓰이는건지 이해가 아직은 안되고 있음.

우선 사용법.

bind( 함수명, (상수 값 or 파라메터 인덱스)~ 쭉 ) ( 아규먼트 )


ex)
boost::bind( func, 1, _1, 2, _3, _2 ) ( 10, 11, 12 );
 == func( 1, 10, 2, 12, 11 ); 와 같다.

// 단, func라는 함수는 다섯개의 인자를 받는 함수여야 함.
// 인자수가 적거나 많으면 컴파일 에러

// function 이나 signal과 연동해서 쓰는법.
int Func( int x, int y )
{
      do something;
      return 0;
}

// 함수의 원형과 같이 펑션과 시그널을 잡아줌. 리턴형 int, 파라메터 int 2개
boost::function< int( int, int ) > f01;
boost::signal< int( int, int ) > s01;

// 인자로 아규먼트를 받도록 구현
f01 = boost::bind( Func, _1, _2 );

boost::signals::connection c01 = s01.connect( boost::bind( Func, _1, _2 ) );
// boost::signals::connection c01 = s01.connect( f01 );  // 위에랑 동일

cout << f01( 10, 20 ) << " " << s01( 20, 30 ) << endl;

//---------------------------------------------------
// 멤버함수를 연결하는 법
struct X {
 int F( int );
};

X x;

boost::bind( $X::F, _1, _2 ) ( x, 10 );

// Function을 써서 사용한 방법. 결과는 위와 동일.
boost::function< int( X*, int ) > f01;
f01 = boost::bind( $X::F, _1, _2 );
f01( &x, 10 );

'Programming > Boost' 카테고리의 다른 글

asio - TCP_server( async )  (0) 2009.12.01
asio -- 1  (0) 2009.12.01
Signal 공부중인거 정리. < 04 >  (0) 2009.08.20
Signal 공부중인거 정리. < 03 >  (0) 2009.08.20
Signal 공부중인거 정리. < 02 > - 1  (0) 2009.08.19
/*     boost connection에 관한 부분     */

boost::signal< void() > sig01;
// signal 이 아니고 signals 임. 주의. 게다가 connection 대문자로 쓰면 다른 의미의 컨넥션이 됨.
boost::signals::connection c01;

// connect 함수의 리턴값이 바로 컨넥션
c01 = sig01.connect( Func() );

// 연결 여부를 리턴하는 함수
if( c01.connected() ) {
    sig01();
}

/*
* boost::connection 헤더에 정의된 모냥
*  // Returns true if the signal and slot are connected
*  bool connected() const { return con.get() && con->signal_disconnect; }
*/

c01.disconnect();      // 연결 끊기

c01.block();              // 임시로 블럭.
c01.unblock();          // 블럭해제

{
    int a02 = 10;
// sig01.connect( Func() );
    boost::signals::scoped_connection c02 = sig01.connect( Func() );
    sig01();
}
// scoped_connection으로 연결했던 signal 이라면 실행되지 않는다.
// 단, scoped 가 아니면 지역변수로 만들었더라도 실행이 된다.
sig01();
cout << a02 << endl;           // 물론 컴파일 에러. a02를 못 찾는다.



ps. 만약 signal 생성시 리턴값이 있는 signal을 만들면
disconnection 이나 block 이후 시그널 호출시 오류가 남.
ex) boost::signal< int() > sig01;
boost::signals::connection c01 = sig01.connect( Func() );

c01.disconnect();   or      c01.block();
sig01();           -- 에러 발생

'Programming > Boost' 카테고리의 다른 글

asio -- 1  (0) 2009.12.01
Bind 공부중인거 정리. < 01 >  (0) 2009.08.20
Signal 공부중인거 정리. < 03 >  (0) 2009.08.20
Signal 공부중인거 정리. < 02 > - 1  (0) 2009.08.19
Signal 공부중인거 정리. < 02 >  (0) 2009.08.19
/*    간단한 함수를 소개    */

boost::signal< void() > sig01;

sig01.connect( 1, Func1() );
sig01.connect( 0, Func2() );

실행결과
Func2()
Func1()

// 컨넥시 인덱스를 넣어주면 자동으로 인덱스 순으로 정렬이 된다.

//-----------------------------------
void Func1( Arg ) {
   to do 1
}
void Func2( Arg ) {
   to do 2
}
void Func3( Arg ) {
   to do 3
}

boost::signal< void( Arg ) > sig02;

sig02.connect( &Func1 );
sig02.connect( &Func2 );
sig02.connect( &Func3 );

sig02( arg );

실행결과
to do 1
to do 2
to do 3

// 컨넥이 된 모든 함수로 arg를 보낸다. 그리고 각 함수가 실행됨.

//-----------------------------------
int Func4( Arg ) {
    return 4;
}
int Func5( Arg ) {
    return 5;
}

// 연결된 함수의 리턴값이 int인 것을 주의
boost::signal< int( Arg ) > sig03;

sig03.connect( &Func4 );
sig03.connect( &Func5 );

cout << sig03( Arg ) << endl;

실행결과
5

// Func4 에서 리턴 4를 하지만 Func5 에서 다시 5를 리턴하므로 결과는 5!! 빠밤!