LoginSignup
1
1

More than 5 years have passed since last update.

libxml2でHTMLを保存した時にmeta charsetの前にmeta http-equivがつかないようにするパッチを作った

Posted at

はじめに

libxml2でHTMLを保存した時にmeta charsetの前にmeta http-equivがつかないようにするパッチを作ったのでメモ。

gnome.orgのBugzillaにBug 728436 – [PATCH] Write meta charset tag instead of meta http-equiv content-typeとして報告済みです。

元々はNokogiriを使っていてこの現象に遭遇しました。additional meta Content-Type is added to HTML5 · Issue #1008 · sparklemotion/nokogiriにイシューが上がっています。

問題

パッチを当てていないlibxml2-2.9.1だと、以下のサンプルプログラム

read_write_html.c
#include <libxml/HTMLparser.h>
#include <libxml/tree.h>
#include <libxml/xmlsave.h>

/*
 * cc -Iinclude -L.libs -lxml2.2 -g read_write_html.c
 */

static xmlDocPtr readHtmlFile(const char *filename) {
    htmlParserCtxtPtr parserCtxt;
    xmlDocPtr doc;

    parserCtxt = htmlNewParserCtxt();
    if (parserCtxt == NULL) {
        fprintf(stderr, "htmlNewParserCtxt failed\n");
        return NULL;
    }

    doc = htmlCtxtReadFile(parserCtxt, "example1.html", NULL, 0);

    htmlFreeParserCtxt(parserCtxt);
    return doc;
}

static int saveHtmlFile(xmlDocPtr doc, const char *filename) {
    int ret;
    xmlSaveCtxtPtr saveCtxt;

    saveCtxt = xmlSaveToFilename(filename, "UTF-8",
        XML_SAVE_FORMAT | XML_SAVE_AS_HTML);
    if (saveCtxt == NULL) {
        fprintf(stderr, "xmlSaveToFilename failed\n");
        return -1;
    }

    ret = xmlSaveDoc(saveCtxt, doc);
    if (ret == -1) {
        fprintf(stderr, "xmlSaveDoc failed\n");
        return -1;
    }

    ret = xmlSaveClose(saveCtxt);
    if (ret == -1) {
        fprintf(stderr, "xmlSaveClose failed\n");
        return -1;
    }

    return 0;
}

int main(int argc, char **argv) {
    xmlDocPtr doc;
    int ret;

    doc = readHtmlFile("example1.html");
    if (doc == NULL) {
        fprintf(stderr, "readHtmlFile failed\n");
        return 1;
    }

    ret = saveHtmlFile(doc, "example1-out.html");
    if (ret == -1) {
        fprintf(stderr, "saveHtmlFile failed\n");
        xmlFreeDoc(doc);
        return 1;
    }

    xmlFreeDoc(doc);
    return 0;
}

で、以下のようにmeta charsetのみを持つhtmlファイルを読み込んで保存すると

example1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML5 example</title>
</head>
<body>
<h1>HTML5 save example</h1>
<p>I would like to meta charset tag is used instead of meta http-equiv.</p>
</body>
</html>

以下のようにmeta charsetタグの前にmeta http-equivタグが付けられてしまいます。

example1-out.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>HTML5 example</title>
</head>
<body>
<h1>HTML5 save example</h1>
<p>I would like to meta charset tag is used instead of meta http-equiv.</p>
</body>
</html>

パッチ

libxml2-2.9.1-HTMLtree-meta-charset.patch
--- libxml2-2.9.1/HTMLtree.c.orig   2013-02-27 14:08:48.000000000 +0900
+++ libxml2-2.9.1/HTMLtree.c    2014-04-18 01:05:26.000000000 +0900
@@ -242,6 +242,12 @@
                (attr->children->type == XML_TEXT_NODE) &&
                (attr->children->next == NULL)) {
            value = attr->children->content;
+           if (!xmlStrcasecmp(attr->name, BAD_CAST"charset"))
+           {
+               content = value;
+               http = 1;
+           }
+           else
            if ((!xmlStrcasecmp(attr->name, BAD_CAST"http-equiv"))
             && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
                http = 1;

このパッチを当てたlibxml2では

example1-out.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTML5 example</title>
</head>
<body>
<h1>HTML5 save example</h1>
<p>I would like to meta charset tag is used instead of meta http-equiv.</p>
</body>
</html>

と余分なmeta http-equivタグが追加されずにmeta charsetタグだけが出力されます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1