スポンサーリンク

gumbo-parserの挙動確認

gumbo-parseがどのようにデータを保持しているのかをチェックするためのコード。

タグはenumで区別するため、タグ名は保持していない。<から始まっていることを利用してstd::regexでタグ名を取得している。

#include <iostream>
#include <fstream>
#include <sstream>

#include <regex>

#include <gumbo.h>
 
std::string getTagName(std::string str) {
    // HTMLのタグ名を取得する関数
    // タグは< > で囲まれているが、attribute等があるかもしれないので
    // < スペース 文字列 という構造になっている部分の文字列部分だけを取り出す
    std::regex tagPattern("<\\s*([^ >]+)\\s*");
    std::smatch matches;
    std::regex_search(str, matches, tagPattern);
    return matches[1].str();
}

void myTraceCore(const GumboNode* node, const char* src) {


    switch (node->type) {
    case GUMBO_NODE_ELEMENT:
    {

        // 要素開始位置
        const char* tag_start = node->v.element.original_tag.data;

        // 要素終了位置
        const char* tag_end = node->v.element.original_end_tag.data;

        std::string tagname;
        // タグ名を抽出
        tagname = getTagName(tag_start);
        std::cout << "tag: '" << tagname << "'" << std::endl;


        // 子要素一覧へアクセス
        const GumboVector* children = &node->v.element.children;

        // 子要素がある場合
        if (children->length > 0) {

            for (unsigned int i = 0; i < children->length; ++i) {
 
                const GumboNode* node = static_cast<GumboNode*>(children->data[i]);

                myTraceCore(node, src);

            }

        }

        // タグ名を抽出
        tagname = getTagName(tag_end);
        std::cout << "tag: '" << tagname << "'" << std::endl;


        break;
    }
    case GUMBO_NODE_TEXT:
        // テキストノードの場合	
        std::cout << "text: '" << node->v.text.text << "'" << std::endl;
        break;
    case GUMBO_NODE_WHITESPACE:
        // 空白ノードの場合
        std::cout << "whitespace: '" << node->v.text.text << "'" << std::endl;
        break;
    default:
        std::cout << "others: '" << node->v.text.text << "'" << std::endl;
        break;
    }
}

void myTrace(std::string html) {

    // Gumboでパース
    GumboOutput* output = gumbo_parse(html.c_str());

    // 自作関数の本体呼び出し
    myTraceCore(output->root,html.c_str());

    // GumboOutputの解放
    gumbo_destroy_output(&kGumboDefaultOptions, output);

}



int main()
{
    std::string html = R"(
<!DOCTYPE html>
<html>
  <head>
    <title>The Title</title>
  </head>
  <body>
    <h1>Test</h1>
  </body>
</html>
)";

    myTrace(html);

}

出力

tag: 'html'
tag: 'head'
whitespace: '
    '
tag: 'title'
text: 'The Title'
tag: '/title'
whitespace: '
  '
tag: '/head'
whitespace: '
  '
tag: 'body'
whitespace: '
    '
tag: 'h1'
text: 'Test'
tag: '/h1'
whitespace: '


'
tag: '/body'
tag: '/html'

属性の取得

node->typeがGUMBO_NODE_ELEMENTの時は、属性を取得できる。

#include <iostream>
#include <fstream>
#include <sstream>

#include <regex>

#include <gumbo.h>
 
// 要素の属性を取得する関数
void myAttributes(const GumboNode* node) {

  if (node->type != GUMBO_NODE_ELEMENT) {
    return;
  }

  // 要素の属性を取得
  const GumboVector* attributes = &node->v.element.attributes;

  // 属性リストへアクセス
  for (unsigned int i = 0; i < attributes->length; ++i) {
    GumboAttribute* attr = (GumboAttribute*)attributes->data[i];
    std::cout << "    ";
    std::cout << "    " << attr->name << " : " << attr->value << std::endl;
  }

}


void myTraceCore(const GumboNode* node, const char* src) {


    switch (node->type) {
    case GUMBO_NODE_ELEMENT:
    {

/* ... */ myAttributes(node); // 要素の取得
/* ... */ break; } /* ... */ } }

      
int main()
{
    std::string html = R"(
<!DOCTYPE html>
<html>
  <head>
    <title id = "bodyid" style="color:red;">The Title</title>
  </head>
  <body>
    <h1>Test</h1>
  </body>
</html>
)";

    myTrace(html);

}

出力

id : bodyid
style : color:red;

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: