HTMLからtagを抽出する の XML/C++版。
Apache Xerces-C 3.1.1 SAXParser を使って、XMLをパースする。
#include <iostream>
#include <string>
#include <locale>
#include <vector>
#include <memory>
#define XERCES_STATIC_LIBRARY
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
class ParseHandler : public xercesc::HandlerBase {
public:
/*
* 以下の 仮想関数 がcallbackされるので好きに使うがいい。
* このサンプルでは
* <img> の src アトリビュート と
* <a> の href アトリビュート
* を抽出する。
*/
virtual void characters(const XMLCh* const chars, const XMLSize_t length) {}
virtual void endDocument() {}
virtual void endElement(const XMLCh* const name) {}
virtual void ignorableWhitespace(const XMLCh* const chars, const XMLSize_t length) {}
virtual void processingInstruction(const XMLCh* const target, const XMLCh* const data) {}
virtual void resetDocument() {}
virtual void startDocument() {}
virtual void startElement(const XMLCh* const name, xercesc::AttributeList& attributes);
std::vector<std::wstring> urls;
};
void ParseHandler::startElement(const XMLCh* const name, xercesc::AttributeList& attr) {
std::wstring element(name);
if ( element == L"a" ) {
std::wstring value(attr.getValue("href"));
if ( !value.empty() ) urls.push_back(value);
} else
if ( element == L"img" ) {
std::wstring value(attr.getValue("src"));
if ( !value.empty() ) urls.push_back(value);
}
}
using namespace xercesc;
using namespace std;
int main() {
wstring xhtml =
L"<?xml version='1.0' ?>"
L"<html><body>"
L" <a href=\"http://qiita.com/episteme\">επιστημη</a>"
L" <img src=\"https://pbs.twimg.com/profile_images/54608127/epi_normal.jpg\"/>"
L"</body></html>";
XMLPlatformUtils::Initialize();
{
auto parser = make_unique<SAXParser>();
auto handler = make_unique<ParseHandler>();
MemBufInputSource source(reinterpret_cast<const XMLByte*>(xhtml.data()), xhtml.size()*sizeof(wchar_t), "xhtml-parse", false);
parser->setDocumentHandler(handler.get());
parser->parse(source);
// 結果を出力
wcout.imbue(locale("japanese"));
for ( const wstring& url : handler->urls ) {
wcout << url << endl;
}
}
XMLPlatformUtils::Terminate();
}