동기. XPath 사용법을 잊다.
결과. XPath 사용법을 다시 익히다. 필요한 것만. 
추가 습득. C 메모리 어렵다.
먼저 다운을(http://tinyxpath.sourceforge.net/) 받고 tinyxpath.lib를 추가 종속성으로 추가한다. 추가 라이브러리 경로도 따로 있다면 잡아주고...
사용 연습 코드.
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(root, expr.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(root, expr.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];
    GetModuleFileName( NULL, 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]
이상.

 
댓글 없음:
댓글 쓰기