HTML Parser 評価
HTMLパーサの主な用途は、クローラを書くときに使ったり、
HTML文書から文書だけを取り出すことでしょう。
あるいは、特定のタグの属性を見て何かするような目的もあります。
しかし、Web frameworkで使う目的は、タグの置換ですから、
オリジナルのHTMLにあって、パースした出力にはタグがなくなっている
ということはあってはなりません。
ここでのHTMLパーサの評価は、
オリジナルのHTMLファイルを読み込んで、
HTMLパーサによってパースした結果をHTMLファイルに戻す。
オリジナルと同じであることが評価されます。
すなわちオリジナルと出力したHTMLファイルの差異が評価ポイントとなります。
評価ポイント
評価ポイントは次のとおり。
- タグが未対応
- タグの欠落
- タグ要素の欠落
- タグが閉じていないケースの対応
- コメントの扱い
- Scriptコードの扱い
- XHTML化
- HTML5への対応
- 文字化け
HTMLパーサ評価用のソースコード
まずは、javax.swing.text.html.parserから。
- HTMLファイルの読み込みは、InputStreamReaderが使えるので、コードセットを指定することができる。
文字化けの原因を回避。 - SAXのハンドラは独自。
コメント用のハンドラがあるのでHTML内のコメントを出力できる。
コメントを出力できないハンドラが多いなかこれは評価できる。 - タグへのパーサからの評価がタグ属性で出力される。
最初にテストコードを動かしたときにオリジナルにない属性が出力されていたので
出力しないようにコードを変更する。 - タグの出力は比較的素直。<BR>タグを<BR></BR>と出力しない。
package ews import java.io._ import javax.servlet.http._ import javax.swing.text._ import javax.swing.text.html._ import javax.swing.text.html.parser._ /** * HtmlParse * * javax.swing.text.html should not be used. * Because it is not thread safe. */ class Htmlparse2Sp (request : HttpServletRequest, response : HttpServletResponse, htmlPath : String) extends TemplSp { var parsed:String = null // override def toString :String = parsed // javax.swing.text.html.parser def html : String = { val htmlFile = new java.io.File(htmlPath) if(htmlFile.exists && htmlPath.toLowerCase.endsWith(".html")){ var input:InputStreamReader = null try { input = new InputStreamReader (new FileInputStream(htmlFile), "UTF-8") // open HTML file val cb = new ParserCallback2 val pd = new ParserDelegator pd.parse(input, cb, true) parsed = cb.toString return parsed } catch { case e:IOException => { println("Exception "+e.getMessage) } } finally { input.close } } null // There is no file. } }
ハンドラのソースコード
package ews import javax.swing.text._ import javax.swing.text.html._ class ParserCallback2 extends HTMLEditorKit.ParserCallback { var buf = new StringBuffer override def toString :String = buf.toString override def handleStartTag(tag:HTML.Tag, attrs:MutableAttributeSet , pos:Int):Unit={ var ok = true var buflocal = new StringBuffer buflocal.append("<"+tag.toString) val attrNames = attrs.getAttributeNames while (attrNames.hasMoreElements) { val attrName = attrNames.nextElement val attrValue = attrs.getAttribute(attrName) if(HTMLEditorKit.ParserCallback.IMPLIED.equals(attrName)){ // error ok = false println("ParserCallback2 [IMPLIED] tag=" + tag.toString + " attrName="+attrName + " attrValue="+attrValue) } else if(HTML.NULL_ATTRIBUTE_VALUE.equals(attrName)){ ok = false println("ParserCallback2 [NULL_ATTRIBUTE_VALUE] tag=" + tag.toString + " attrName="+attrName + " attrValue="+attrValue) } else if(HTML.Attribute.ENDTAG.equals(attrName)){ ok = false println("ParserCallback2 [ENDTAG] tag=" + tag.toString + " attrName="+attrName + " attrValue="+attrValue) } buflocal.append(" " + attrName + "=\"" + attrValue + "\"") if (attrName == StyleConstants.NameAttribute && tag == HTML.Tag.CONTENT) { } } buflocal.append(">") if(ok) buf.append(buflocal) } override def handleEndTag(tag:HTML.Tag, pos:Int):Unit={ buf.append("</"+tag.toString+">\n") } override def handleSimpleTag(tag:HTML.Tag, attrs:MutableAttributeSet , pos:Int):Unit={ handleStartTag(tag,attrs,pos) } override def handleText(ch:Array[Char],length:Int):Unit={ buf.append(new String(ch)) } override def handleComment(ch:Array[Char],length:Int):Unit={ val str = new String(ch) if(str.trim.length > 0) buf.append("<!--\n"+str+"\n-->\n") } override def handleEndOfLineString(eol:String):Unit={ buf.append(new String(eol)) } def handleError(ln:Int, errorMsg:String):Unit={ println("ERROR line number="+ln + " " + errorMsg) } }
コメントを残す
コメントを投稿するにはログインしてください。