HTML Parser 評価 javax.swing.text.html.parser

Posted 2011年8月29日 by

HTML Parser 評価

HTMLパーサの主な用途は、クローラを書くときに使ったり、
HTML文書から文書だけを取り出すことでしょう。
あるいは、特定のタグの属性を見て何かするような目的もあります。

しかし、Web frameworkで使う目的は、タグの置換ですから、
オリジナルのHTMLにあって、パースした出力にはタグがなくなっている
ということはあってはなりません。

ここでのHTMLパーサの評価は、
オリジナルのHTMLファイルを読み込んで、
HTMLパーサによってパースした結果をHTMLファイルに戻す。
オリジナルと同じであることが評価されます。

すなわちオリジナルと出力したHTMLファイルの差異が評価ポイントとなります。

評価ポイント

評価ポイントは次のとおり。

  1. タグが未対応
  2. タグの欠落
  3. タグ要素の欠落
  4. タグが閉じていないケースの対応
  5. コメントの扱い
  6. Scriptコードの扱い
  7. XHTML化
  8. HTML5への対応
  9. 文字化け

HTMLパーサ評価用のソースコード

まずは、javax.swing.text.html.parserから。

  1. HTMLファイルの読み込みは、InputStreamReaderが使えるので、コードセットを指定することができる。
    文字化けの原因を回避。
  2. SAXのハンドラは独自。
    コメント用のハンドラがあるのでHTML内のコメントを出力できる。
    コメントを出力できないハンドラが多いなかこれは評価できる。
  3. タグへのパーサからの評価がタグ属性で出力される。
    最初にテストコードを動かしたときにオリジナルにない属性が出力されていたので
    出力しないようにコードを変更する。
  4. タグの出力は比較的素直。<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)
	}
}

Post Details

コメントを残す