2014년 6월 29일 일요일

[복습] Review XPath with TinyXPath

본론 시작.
동기. XPath 사용법을 잊다.
결과. XPath 사용법을 다시 익히다. 필요한 것만. 
추가 습득. C 메모리 어렵다.

먼저 다운을(http://tinyxpath.sourceforge.net/) 받고 tinyxpath.lib를 추가 종속성으로 추가한다. 추가 라이브러리 경로도 따로 있다면 잡아주고...

쓸 때 에러나서 _CRT_SECURE_NO_WARNINGS 추가로 넣어줘야 하는데 귀찮은데 다른 거 알아볼까... 문자 집합은 사용 하지도 않음...

사용 연습 코드.

MyTinyUtil.h

#ifndef _MY_CUSTOM_TINY_H_
#define _MY_CUSTOM_TINY_H_

#include "xpath_processor.h"
#include <iostream>
#include <string>
#include <Windows.h>
#include <list>

bool MyTi_InitMyUtil();     //아무 일도 하지 않는다.
bool MyTi_QuitMyUtil();   //생성된 메모리 해제한다.
unsigned int MyTi_GetNodesByExpr(TiXmlElement *root, std::string expr, TinyXPath::node_set **nodeSet);
UINT MyTi_GetAttributesByExpr(TiXmlElement *root, std::string expr, std::list<const TiXmlAttribute*> **attr_list);
std::string MyTi_ExePath();
void MyTi_PrintNodeValue(const TiXmlNode *pNode);

#endif

------------------------------------------------------------------------------------------------------------
MyTinyUtil.cpp

#include "MyTinyUtil.h"

static TinyXPath::expression_result exprResult;

static std::list<TinyXPath::xpath_processor*> xProcList;
static std::list<TinyXPath::expression_result*> eResultList;

bool MyTi_InitMyUtil(){
        //nothing done here.
return true;
}

bool MyTi_QuitMyUtil(){
std::list<TinyXPath::xpath_processor*>::iterator iter;
for(iter = xProcList.begin(); iter != xProcList.end(); iter++){
delete *iter;
}
return true;
}

/*
* @root : 최상위 노드
* @expr : 표현식
* @nodeSet : 반환받을 노드 집합
* return : 집합의 원소 수
* 루트를 기준으로, 표현식에 적합한 노드 집합을 얻는다. 단, 표현식이 잘못될 시 프로그램이 죽는다..
*/
unsigned int MyTi_GetNodesByExpr(TiXmlElement *root ,std::string expr, TinyXPath::node_set **nodeSet){
TinyXPath::xpath_processor *xproc = new TinyXPath::xpath_processor(rootexpr.c_str());

exprResult = (xproc->er_compute_xpath());
*nodeSet = exprResult.nsp_get_node_set();

xProcList.push_back(xproc);

return (*nodeSet)->u_get_nb_node_in_set();
}

/*
* @root : 최상위 노드
* @expr : 표현식
* @attr_list : 반환받을 속성 리스트
* return : 리스트의 원소 수
* 루트를 기준으로, 표현식에 적합한 속성 집합을 얻는다. 속성을 검색할 때, 속성들만 다 가져오는 듯.
*/
UINT MyTi_GetAttributesByExpr(TiXmlElement *root, std::string expr, std::list<const TiXmlAttribute*> **attr_list){
TinyXPath::xpath_processor *xproc = new TinyXPath::xpath_processor(rootexpr.c_str());
exprResult = (xproc->er_compute_xpath());

xProcList.push_back(xproc);

TinyXPath::node_set* nodeSet = exprResult.nsp_get_node_set();
if(*attr_list == nullptr){
*attr_list = new std::list<const TiXmlAttribute*>();
}
UINT numberOfAttrNode = nodeSet->u_get_nb_node_in_set();

const TiXmlNode *node = nullptr;
for(UINT i = 0; i < numberOfAttrNode; i++){
const TiXmlAttribute * attr = nullptr;
node = nodeSet->XNp_get_node_in_set(i);
if(node != nullptr){
attr = node->ToElement()->FirstAttribute();
(*attr_list)->push_back(attr);
}
}
return numberOfAttrNode;
}

/*
* return : 현재 작업 경로
*/
std::string MyTi_ExePath() {
    char buffer[MAX_PATH];
    GetModuleFileNameNULL, buffer, MAX_PATH );
    std::string::size_type pos = std::string( buffer ).find_last_of( "\\/" );
    return std::string( buffer ).substr( 0, pos);
}

/*
* @pNode : 출력할 노드
* 노드 이름과 내부 값을 출력하는데... to be continue...
*/
void MyTi_PrintNodeValue(const TiXmlNode *pNode){
switch (pNode -> Type ())  {
            case TiXmlNode::DOCUMENT :
   //fprintf (Fp_out, "\nStart document\n");
            break;
  case TiXmlNode::ELEMENT :
  
   std::cout<<"Element "<<pNode -> ToElement () -> Value ()<<std::endl;
   if(pNode->FirstChild() != nullptr){
  MyTi_PrintNodeValue(pNode->FirstChild());
   }
            break;

   case TiXmlNode::COMMENT :
   std::cout<<"Comment"<<pNode -> ToComment () -> Value ()<<std::endl;
            break;
   case TiXmlNode::TEXT :
   std::cout<<"TEXT"<<pNode -> ToText () -> Value ()<<std::endl;
            break;
     case TiXmlNode::UNKNOWN :
   case TiXmlNode::DECLARATION :
            break;
     default :
  assert (false);
      }
}

------------------------------------------------------------------------------------------------------------

색 바꾸기 힘드므로 이하는 안 바꿈.

참고 XML 파일 내용
----------------------------------------------------------------------

<?xml version="1.0" encoding="UTF" standalone="yes" ?> 
<main>
    <main_node>
        <class ids="343가">1학년</class>
        <class id="210ㅇ10">2학년</class>
        <class id="1000">3학년</class>
        <class id="200">4학년</class>
        <class id="3000">5학년</class>
        <class id="400">6학년</class>
        <class id="5000">7학년</class>
        <class_name>
            <code>예술반</code>
            <code_name>미술</code_name>
            <code_count>10명</code_count>
        <class_teacher>
            <teacher>홍길동 선생</teacher>
            <teacher_sex>남자</teacher_sex>
        </class_teacher>
            <school>
                <code>12345</code>
                <code_name id="16000">예술학교</code_name>
            </school>
         </class_name>
     </main_node>
</main>
----------------------------------------------------------------------

이하 연습 코드. 목적은 속성을 가지되, id라는 속성을 가져야 하고 그 값이 400인 노드를 얻어와 이를 출력한다.
또한, id라는 속성을 모두 가져와 그 속성값을 출력한다.

삽질 시작.

#include "MyTinyUtil.h"

#include <iostream>

int main(int argc, char* argv[]){

std::cout<<"startedd..."<<std::endl;

MyTi_InitMyUtil();

std::string path = MyTi_ExePath() + "\\sample.xml";
TiXmlDocument *pDocument = new TiXmlDocument;
if(!pDocument->LoadFile(path.c_str())){
std::cout<<"no file"<<std::endl;
return 231;
}

TiXmlElement *Root = pDocument->RootElement();

std::cout<<Root->Value()<<std::endl;
TinyXPath::node_set *pNodeSet = nullptr;

UINT nSize = MyTi_GetNodesByExpr(Root, "//*[@id='400']", &pNodeSet);    //가져와, 속성명이 id이고 그 값이 400인

if(pNodeSet == nullptr) return 0;

        //노드 이름 출력!
for(UINT i = 0; i < nSize; i++){
std::cout<<"node name is "<<pNodeSet->XNp_get_node_in_set(i)->Value()<<std::endl;
MyTi_PrintNodeValue(pNodeSet->XNp_get_node_in_set(i));
}

std::list<const TiXmlAttribute*> *pAttrList = nullptr;
nSize = MyTi_GetAttributesByExpr(Root, "//*[@id]", &pAttrList);  //가져와 누구를? id란 속성명 갖고 있는 모든노드속성
if(pAttrList == nullptr){
std::cout<<"null"<<std::endl;
return -3;
}

        //속성값 출력
std::list<const TiXmlAttribute*>::iterator iter;
for(iter = pAttrList->begin(); iter != pAttrList->end(); iter++){
std::cout<<(*iter)->Value()<<std::endl;
}

MyTi_QuitMyUtil();

delete pDocument;
delete pAttrList;

return 0;
}

결과 화면.

[그림 1]
이상.

댓글 없음:

댓글 쓰기