前の関連記事: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 )) |
16行目以降は動作確認用のコードです。
関数html2elem()はHTMLをElementTreeにするPythonスクリプト、関数formatHTML()はHTMLを整形するPythonスクリプトのものです。
ElementTree < root >< doctype ><!DOCTYPE html></ 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]) |
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
空要素は子要素をもつことができない要素のことで、終了タグが禁止されています。
0 件のコメント:
コメントを投稿