Xml Node 읽기 저장

TinyXml을 이용해 편하게 Xml Node를 읽고 저장해보자.
구현 자체의 설명 보다는 XmlNode의 사용법에 대해서 자세하게 다룰것이다.

사용되는 기능은 크게 TinyXml을 다루는 XmlNode와 문자열과 숫자 변환을 다루는 StringUtil 함수들이다.

 

<Xml노드와 Xml의 관계>

XmlNode 클래스를 Xml 구조와 비교해 보자.

<?xml version="1.0" encoding="euc-kr" ?>
<root>
    <actor race="human">철수</actor>
</root>

xml version~~~ 헤더는 무시하고 넘어간다.
<root> ~~ </root>와 <actor>  ~~ </actor>를 XML용어로 "엘리먼트"라 한다.
철수는 "엘리먼트 내용",  race="human"은 속성으로 race는 "속성이름", human은 "속성값"이라 부른다.

XmlNode에서는 "엘리먼트", "내용", "속성이름", "속성값"에 대해서 다룬다.

엘리먼트 : 엘리먼트의 이름을 가져오거나 설정한다. 여기서는 root나 actor를 나타낸다.
std::string*    XmlNode::GetName()
XmlNode&    XmlNode::SetName( const char* szName )

엘리먼트 내용: 엘리먼트의 내용을 가져오거나 설정한다. 여기서는 철수를 나타낸다.
XmlNode&   XmlNode::SetData( std::string data )
XmlNode&   XmlNode::SetData( const char* pData )
std::string*    XmlNode::GetData()

속성이름과 속성값: 속성 이름과 속성값을 설정한다.
void  XmlNode::AddAttribute( const char* pName, const char* pValue )

 

<기타 중요 메쏘드>

XmlNode를 어태치하거나 디태치 할 수 있다.
XmlNode* XmlNode::AttachChild( XmlNode* pChild )
void    XmlNode::DetachChild( XmlNode* pChild );

pName에 해당하는 엘리먼트를 검색해 nodeArr 배열에 추가한다.
void XmlNode::FindNode( const char* pName, XmlNodeVector& nodeArr )

< XmlNode의 읽기, 저장, XmlNode 생성>

XmlNode를 다루는 3가지 전역 함수가 있다.

XmlNode root를 szName이라는 이름으로 Xml 파일을 저장한다.
void     WriteXml( const char* szName, XmlNode* root );

szName 이름을 가진 Xml 파일을 읽어 XmlNode*로 리턴한다. (XmlNode는 나중에 delete 시켜 줘야한다.)
XmlNode*    ReadXml( const char* szName );

szName을 엘리먼트 이름으로 정하고 XmlNode를 생성한다.
XmlNode*    CreateXmlNode( char* szName )

<문자열 변환 함수들>

bool, float, Vector2, Vector3, Vector4, Matrix를 문자열과 상호 변환 할 수 있는 함수 이다.
이들 함수를 사용해서 XmlNode의 엘리먼트, 엘리먼트 내용, 속성이름, 속성값을 편리하게 처리 할 수 있다.

bool            ToBool( const std::string& str );

std::string    ToString( bool bFlag );

int                ToInt( const std::string& str );

std::string        ToString( int num );

float            ToFloat( const std::string& str );

std::string        ToString( float num );

base::Vector2    ToVector2( const std::string& str );

std::string        ToString( const base::Vector2& vector );

base::Vector3    ToVector3( const std::string& str );

std::string        ToString( const base::Vector3& vector );

base::Vector4    ToVector4( const std::string& str );

std::string        ToString( const base::Vector4& vector );

base::Matrix    ToMatrix( const std::string& str );

std::string        ToString( const base::Matrix& mat );

 

<예제들>

아래 예제는 3d.xml을 읽어서 3d_test.xml 파일로 저장한다.

    XmlNode* pXmlNode = ReadXml( "3d.xml" );

    WriteXml( "3d_test.xml", pXmlNode );

    delete pXmlNode;

다음 예제는 bool, int, float, Vector2, Vetor3, Vector를 엘리머트로 만들어  3d_type.xml 파일로 저장한다.

    XmlNode* rootXmlNode = CreateXmlNode( "root" );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "bool" ).SetData( ToString( true ) );

    bool bFlag = ToBool( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "Int" ).SetData( ToString( 10 ) );

    int num = ToInt( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "Float" ).SetData( ToString( 10.7f ) );

    float fnum = ToFloat( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "Vector2" ).SetData( ToString( base::Vector2( 2.2f, 2.3f ) ) );

    base::Vector2 vec2 = ToVector2( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "Vector3" ).SetData( ToString( base::Vector3( 1.2f, 2.4f, 3.5f ) ) );

    base::Vector3 vec = ToVector3( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    pXmlNode->SetName( "Vector4" ).SetData( ToString( base::Vector4( 1.1f, 2.2f, 3.3f, 4.4f ) ) );

    base::Vector4 vec4 = ToVector4( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode = new XmlNode;

    base::Matrix mat;

    mat.Init();

    for( int i = 1; i <= 4; ++i )

        for( int j = 1; j <= 4; ++j )

        {

            mat.m[i-1][j-1] = float(i*10 + j);

        }

    pXmlNode->SetName( "Matrix" ).SetData( ToString( mat ) );

    base::Matrix mat1 = ToMatrix( *pXmlNode->GetData() );

    rootXmlNode->AttachChild( pXmlNode );

    WriteXml( "3d_type.xml", rootXmlNode );

    delete rootXmlNode;

다음의 예제는 CreateXmlNode(), AttachChild(), AddAttribute(), FindNode()를 사용한 예제이다.

    rootXmlNode = CreateXmlNode( "root" );

 

    pXmlNode = CreateXmlNode( "Actor" );

    rootXmlNode->AttachChild( pXmlNode );

 

    pXmlNode->AddAttribute( "철수", "311" );

    pXmlNode->AttachChild( CreateXmlNode( "model" ) )->AttachChild( CreateXmlNode( "Vector" ) )->

            SetData( ToString(base::Vector3( 1.1f, 2.4f, 3.7f ) ) );

 

    rootXmlNode->AttachChild( CreateXmlNode("Actor") )->

            AttachChild( CreateXmlNode( "model" ) )->AttachChild( CreateXmlNode( "Vector" ) )->

            SetData( ToString(base::Vector3( 1, 2, 3 ) ) );

 

    XmlNodeVector nodeArr;

    rootXmlNode->FindNode( "root/Actor/model/Vector", nodeArr );

    if( nodeArr.empty() == false )

    {

        nodeArr[1]->AddAttribute( "type", "position" );

    }

 

    nodeArr.clear();

    rootXmlNode->FindNode( "root/Actor/model/Vector", nodeArr );

    if( nodeArr.empty() == false )

    {

        XmlNode* kXmlNode = nodeArr[0];

        base::Vector3 vec= ToVector3( *kXmlNode->GetData() );

        std::cout << "벡터 출력" << std::endl;

    }

 

    WriteXml( "3d_math.xml", rootXmlNode );

    delete rootXmlNode;

프로젝트: TinyXmlTest1.zip