TinyXml 노드로 읽기

Xml이 구조가 편해 보이기는 하지만 실제로 읽거나 쓸때 번거롭다.
읽기만이라도 편하게 하기 위해 TinyXml로 데이터를 읽어서 TreeNode로 데이터를 읽어 본다.

Node 클래스: TiXmlNode::ELEMENT가 불려질때 마다 Node 클래스의 객체를 생성한다.
                  이때 TinyXml의 Attribute를 Node::AddAttribute()를 통해 저장한다.
                  TiXmlNode::TEXT는 Node::Setdata()로 저장한다.

실제 구현 코드는 아래와 같다.

void ReadXmlNode(TiXmlNode *pNode, Node* dataNode )

{

    if(pNode)

    {

        switch(pNode->Type())

           {

        case TiXmlNode::COMMENT:

            //std::cout << "COMMENT: " << pNode->Value() << std::endl;

            break;

           case TiXmlNode::DECLARATION:

            //std::cout << "DECLARATION: " << std::endl;

               break;

 

           case TiXmlNode::ELEMENT:

               {

                //std::cout << "ELEMENT: [" << pNode->ToElement()->Value() << "]" << std::endl;

                Node* child = new Node;

                dataNode->AttachChild( child );

                dataNode = child;

 

                dataNode->SetClassName( pNode->ToElement()->Value() );

                   TiXmlAttribute *pAttr = pNode->ToElement()->FirstAttribute();

                   while(pAttr)

                   {

                    dataNode->AddAttribute( pAttr->Name(), pAttr->Value() );

                    //std::cout << pAttr->Name() << "=\"" << pAttr->Value() << "\"" << std::endl;

                          pAttr = pAttr->Next();

                   }

            }

               break;

 

           case TiXmlNode::TEXT:

            TiXmlText* pText = pNode->ToText();

            if(pText)

            {

                dataNode->SetData( new DataType( pText->Value() ) );

                //std::cout << "TEXT:  " << pText->Value() << std::endl;

            }

            break;

           }

 

           for(TiXmlNode *pNext = pNode->FirstChild(); pNext; pNext = pNext->NextSibling())

            ReadXmlNode(pNext, dataNode);

    }

}

ReadXmlNode()로 XML 데이터를 읽고나서  검색하는 방법은 다음과 같다.

Node::FindNode()의 첫 번째 인자는 "MyNode1/MyNode2/num" 검색할 노드의 ClassName( XML에서는 Element)을 "/" 분리자에 의해서 루트 노드 "MyNode1"로 부터  자식 "MyNode2", 손자 "num"까지 노드가 있으면 두 번째 인자 NodeVector에 저장하여 리턴한다.

void ReadXmlToNode()

{

    TiXmlDocument doc;

    if ( doc.LoadFile("3d.xml") == false )

    {

        return//로딩 실패

    }

 

    Node* parent = new Node;

    ReadXmlNode( &doc, parent );

    std::cout << "=======================================================" << std::endl;

    Node::PrintAll( parent );

    std::cout << "=======================================================" << std::endl;

 

    NodeVector nodeArr;

    std::cout << "************** Find MyNode1/MyNode2/num ****************" << std::endl;

    parent->FindNode( "MyNode1/MyNode2/num", nodeArr );

    for( NodeVector::iterator iter = nodeArr.begin(); iter != nodeArr.end(); ++iter )

    {

        Node* pNode = *iter;

        std::cout << pNode->GetParent()->GetParent()->GetClassName()->c_str()

                        << " | "  << pNode->GetParent()->GetClassName()->c_str()

                        << " | "  << pNode->GetClassName()->c_str() << std::endl;

    }

    delete parent;

}

Node 클래스는 Scene 구조의 축소형으로 되어 있다. XML 이외에 렌더링 엔진에도 사용할 수 있을 것이다.
Node 클래스를 템플릿으로 만들어 놓은 TreeNode도 있다.

프로젝트: TinyXmlTest.zip