Element オブジェクトをHTMLに変換するPythonスクリプト

公開日: 2018年04月18日 更新日: 2019年05月11日

旧ブログ

t f B! P L
Element オブジェクトをルートとしてその子孫のノードをHTMLに変換するPythonスクリプトです。

前の関連記事:HTMLをElementTreeにするPythonスクリプト


Element オブジェクトをHTMLに変換するelem2html.py 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from xml.etree import ElementTree
def elem2html(elem):  # ElementオブジェクトをHTMLにして返す。
    doctypetxt = ""
    doctype = elem.find(".//doctype"# ドキュメントタイプ宣言を入れたノードを取得。
    if doctype is not None# ドキュメントタイプ宣言を入れたノードが取得出来た時。
        doctypetxt = doctype.text  # ドキュメントタイプ宣言を取得。
        elem.find(".//doctype/..").remove(doctype)  # doctypeノードを削除。
    h = ElementTree.tostring(elem, encoding="unicode", method="html")
    emptytags = "source", "track", "wbr", "embed", "root"  # 終了タグがついてくる空要素などの終了タグを削除。
    for tag in emptytags:
        h = h.replace("".join(["</", tag, ">"]), "")
    h = h.replace("<root>", "")
    return "".join([doctypetxt, h])
if __name__ == "__main__":
    from html2elem import html2elem
    from formathtml import formatHTML
    s = """\
<!DOCTYPE html><html>
        <head>
                <meta charset="utf-8">
                <title>My test<br> page</title>
        </head>
        <body>
                <img src="images/firefox-icon.png" alt="My test image">
        </body>
</html> """
    root = html2elem(s)  # ElementTreeのルートを取得。
    print("\nElementTree\n")
    print(ElementTree.tostring(root, encoding="unicode"))
    h = elem2html(root)  # ルートの子孫をHTMLの文字列に変換。
    print("\nElementTree to HTML\n")
    print(formatHTML(h, reset=True))
関数elem2html()にElementオブジェクトを渡すとHTMLの文字列が返ってきます。

16行目以降は動作確認用のコードです。

関数html2elem()はHTMLをElementTreeにするPythonスクリプト、関数formatHTML()はHTMLを整形するPythonスクリプトのものです。
ElementTree
 
<root><doctype>&lt;!DOCTYPE html&gt;</doctype><html>
  <head>
    <meta charset="utf-8" />
    <title>My test<br /> page</title>
  </head>
  <body>
    <img alt="My test image" src="images/firefox-icon.png" />
  </body>
</html> </root>
 
ElementTree to HTML
 
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>My test
   <br>
    page
  </title>
 </head>
 <body>
  <img alt="My test image" src="images/firefox-icon.png">
 </body>
</html>
動作確認用コードを実行するとこのような結果になります。

まずHTMLをhtml2elem()に渡して作成したElementTreeをElementTree.tostring()でユニコード文字列に変換してXMLを出力しています。

XMLではすべて終了タグがついていることがわかります。

ElementTreeにパースする文字列がインデントしてあるとそれぞれtext属性、tail属性にインデントが入ってくるので、html2elem()に渡したHTMLがインデントされていると、ElementTree.tostring()で返ってくるXMLもインデントがそのまま表示されています。

関数elem2html()にそのElementオブジェクトを渡してHTMLを取得します。

さらにそのHTMLを関数formatHTML()に渡して整形していますが、すでにインデントされていると、きれいに整形できないので、formatHTML()の第2引数(Noneでなければ何でも可)を渡してまず空白文字だけのtextとtailを削除しています。

スクリプトの解説

4
5
6
7
8
9
10
11
12
13
14
15
def elem2html(elem):  # ElementオブジェクトをHTMLにして返す。
    doctypetxt = ""
    doctype = elem.find(".//doctype"# ドキュメントタイプ宣言を入れたノードを取得。
    if doctype is not None# ドキュメントタイプ宣言を入れたノードが取得出来た時。
        doctypetxt = doctype.text  # ドキュメントタイプ宣言を取得。
        elem.find(".//doctype/..").remove(doctype)  # doctypeノードを削除。
    h = ElementTree.tostring(elem, encoding="unicode", method="html")
    emptytags = "source", "track", "wbr", "embed", "root"  # 終了タグがついてくる空要素などの終了タグを削除。
    for tag in emptytags:
        h = h.replace("".join(["</", tag, ">"]), "")
    h = h.replace("<root>", "")
    return "".join([doctypetxt, h])
xml.etree.ElementTree.tostring()メソッドでencodingをunicode、methodにhtmlに指定すればelemとその子孫をHTMLの文字列に変換できるはずですが、空要素なのに終了タグがついてくるものがあります。

Python3.6のElementTree.pyのHTML_EMPTYに空要素のタプルが定義してありますが、Empty element (空要素) - 用語集 | MDNと比べると、source、track、wbr、embed、keygenが含まれておらず、これらの終了タグが出力されてしまうからです。

HTML_EMPTYにはbasefont、frame、isindexも入っていますが、これらのタグはすでに廃止されています。

すでに廃止されているkeygen、basefont、frame、isindexを除いて、source、track、wbr、embedについてくる終了タグを13行目で削除しています。

HTMLをElementTreeにするPythonスクリプトで独自に追加した<doctype>要素や<root>要素についても、それぞれドキュメントタイプ宣言の要素、rootノードの削除という処理をしています。

参考にしたサイト


Empty element (空要素) - 用語集 | MDN
空要素は子要素をもつことができない要素のことで、終了タグが禁止されています。

次の関連記事:HTMLのインラインstyle属性からCSSを生成するPythonスクリプト

ブログ検索 by Blogger

Translate

«
Apr. 2018
»
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Created by Calendar Gadget

QooQ