본론 시작.
동기. 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());
//위의 넘은 나중에 알아서 제거된다. delete로..
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" x="13반" y="3410" w="1030" h="030">6학년</class>
<class id="5000" x="3반" y="340" w="30" h="30">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>
<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" x="13반" y="3410" w="1030" h="030">6학년</class>
<class id="5000" x="3반" y="340" w="30" h="30">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;
}
//속성값 출력 : 변경되었다. FirstAttribute는 Next 메서드로 다음 속성을 가져온다. 없으면 NULL이 반환된다.
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);
}
}
const TiXmlAttribute * attr = nullptr;
node = nodeSet->XNp_get_node_in_set(i);
if(node != nullptr){
attr = node->ToElement()->FirstAttribute();
(*attr_list)->push_back(attr);
}
}
MyTi_QuitMyUtil();
delete pDocument;
delete pAttrList;
return 0;
}
결과 화면.
[그림 1]
이상.
댓글 없음:
댓글 쓰기