RapidXml에서 문자열 파싱하기 및 주의사항
C++에서 XML 파싱에 사용하는 라이브러리 중 RapidXml이 있습니다.
속도가 빠르고, 헤더 파일로만 되어 있어서 단순히 파일을 복사하는 정도만으로 쉽게 사용할 수 있다는 장점이 있습니다.
더군다나 MIT 라이선스로 사용 가능하므로 상업용 프로그램에도 유용하게 사용할 수 있습니다.
공식 사이트: http://rapidxml.sourceforge.net
그런데 주의사항이 있습니다.
우선 아래를 봐주시기 바랍니다.
위와 같이 하면 std::string으로부터 XML을 파싱할 수 있습니다.
여기서 빨간색 부분을 보시면 const char*를 char*로 변환하는데요, 해보시면 별 문제 없이 잘되는 것 같아 보입니다.
하지만 parse()가 문자열을 변경하지 않는다는 보장이 없습니다.만약 변경해버린다면 예상치 못한 문제가 발생할 것이고, 정말 찾기 힘든 버그가 될 것입니다. 별 문제가 없더라도 아래와 같이 문자열을 복사해서 사용하는 방법을 권장해드립니다.
네 위와 같이 하면... 안됩니다!
원인은 빨간색으로 표시해두었습니다.
parse()는 내부적으로 dom 객체를 만들면서 문자열을 복사하지 않습니다.
기존의 문자열을 그대로 참조합니다.
그래서 parse() 후에 parse()에 사용한 문자열의 데이터를 해제해버리면, 제대로 동작하지 않습니다.
결과적으로 문자열을 파싱하는 방법은 아래와 같습니다.
참고 자료
[1] Jordan Schaenzle, "RapidXml – A Lightweight xml Library for C++", http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/, 2015-05-04 확인
[2] mathematician1975의 답변, "RapidXML compilation error parsing string", http://stackoverflow.com/questions/11604818/rapidxml-compilation-error-parsing-string, 2015-05-04 확인
속도가 빠르고, 헤더 파일로만 되어 있어서 단순히 파일을 복사하는 정도만으로 쉽게 사용할 수 있다는 장점이 있습니다.
더군다나 MIT 라이선스로 사용 가능하므로 상업용 프로그램에도 유용하게 사용할 수 있습니다.
공식 사이트: http://rapidxml.sourceforge.net
그런데 주의사항이 있습니다.
우선 아래를 봐주시기 바랍니다.
string strXml = "<?xml version="1.0" encoding="utf-8"?><books> ... (중략) ... </books>";
xml_document<> doc;
doc.parse<0>((char*)strXml.c_str());
xml_node<>* root = doc.first_node();
printf("root 노드 이름: %s\n", root->name());
위와 같이 하면 std::string으로부터 XML을 파싱할 수 있습니다.
여기서 빨간색 부분을 보시면 const char*를 char*로 변환하는데요, 해보시면 별 문제 없이 잘되는 것 같아 보입니다.
하지만 parse()가 문자열을 변경하지 않는다는 보장이 없습니다.만약 변경해버린다면 예상치 못한 문제가 발생할 것이고, 정말 찾기 힘든 버그가 될 것입니다. 별 문제가 없더라도 아래와 같이 문자열을 복사해서 사용하는 방법을 권장해드립니다.
string strXml = "<?xml version="1.0" encoding="utf-8"?><books> ... (중략) ... </books>";
char* sz = new char[strXml.size() + 1];
strcpy(sz, strXml.c_str());
xml_document<> doc;
doc.parse<0>(sz);
delete [] sz;
xml_node<>* root = doc.first_node();
printf("root 노드 이름: %s\n", root->name());
네 위와 같이 하면... 안됩니다!
원인은 빨간색으로 표시해두었습니다.
parse()는 내부적으로 dom 객체를 만들면서 문자열을 복사하지 않습니다.
기존의 문자열을 그대로 참조합니다.
그래서 parse() 후에 parse()에 사용한 문자열의 데이터를 해제해버리면, 제대로 동작하지 않습니다.
결과적으로 문자열을 파싱하는 방법은 아래와 같습니다.
string strXml = "<?xml version="1.0" encoding="utf-8"?><books> ... (중략) ... </books>";
char* sz = new char[strXml.size() + 1];
strcpy(sz, strXml.c_str());
xml_document<> doc;
doc.parse<0>(sz);
xml_node<>* root = doc.first_node();
printf("root 노드 이름: %s\n", root->name());
delete [] sz;
참고 자료
[1] Jordan Schaenzle, "RapidXml – A Lightweight xml Library for C++", http://spin.atomicobject.com/2012/05/20/rapidxml-a-lightweight-xml-library-for-c/, 2015-05-04 확인
[2] mathematician1975의 답변, "RapidXML compilation error parsing string", http://stackoverflow.com/questions/11604818/rapidxml-compilation-error-parsing-string, 2015-05-04 확인
댓글
댓글 쓰기