HTMLパーサの差し替え
org.htmlparser.saxのバージョンは2.0をタグ拡張したバージョンにするため
以下のハンドラコードにを切り替える。
class Htmlparse5Spは、class Htmlparse4Spのハンドラを
生成しているところを、
val cb = new ParserCallback4 から val cb = new ParserCallback5 に書き換えればよい。
これで、オリジナルのHTMLファイルのScriptタグのなかにあるJavascriptのコードがなくならない。
このコードについて、このページを掲載してからいろいろとテストしたところ、
タグの再現性がないことを確認しました。
再現しない理由は、
- HTML parserが解析しないタグが他にもあること。
- タグの開始と終了が完全でないとエラーとなる。これは、ソースコードにあるstackでタグ関係をチェックしているために対が崩れるとエラーとしていることです。この場合このコードは不要です。
対応は、
HTML parserのオリジナルのコードにさらに定義されていないタグのクラス定義を追加し、
stackのタグ対チェックを外すことです。
これ以外にも、処理ロッジを変更しているので、新しいコードが完成次第リリースしますので、お試しください。
以下のコードはさらに差し替えになります。
package ews.servlet.sp import java.util.HashMap import org.xml.sax._ import org.xml.sax.helpers.DefaultHandler import scala.collection.JavaConversions._ import scala.collection.mutable.Stack import seedo._ class ParserCallback5(pMap:HashMap[String,Array[String]]) extends DefaultHandler { var buf = new StringBuffer val stack = new Stack[String] // For indent inspection of tag val stackChange = new Stack[ExecTag] // For substitution var locator:Locator = null override def toString :String = buf.toString override def setDocumentLocator (locator:Locator) :Unit= { this.locator = locator } override def startDocument ():Unit= { System.out.println("Start document");} override def endDocument():Unit= { System.out.println("End document");} override def startElement ( uri:String, name:String, qualifiedName:String , attrs:Attributes ):Unit={ var buflocal = new StringBuffer stack.push(name) buflocal.append("<"+name) var fullFag = false // for (idx <- 0 to attrs.getLength - 1){ val attributeType = attrs.getType(idx) val attrLocalName = attrs.getLocalName(idx) val attrName = attrs.getQName(idx) val attrValue = attrs.getValue(idx) if(attrLocalName.length > 0 && !"#text".equals(attrLocalName)){ buflocal.append(" " + attrLocalName + "=\"" + attrValue + "\"") if("class".equals(attrName) && attrValue.startsWith("seedo:")){ val execCommand = attrValue.split(":") // Each element is separated. if(execCommand.length >= 3) { // It doesn't substitute it if there are neither a class name nor a function name. stackChange.push(new ExecTag( stack.length ,name ,execCommand ,new StringBuffer // The tag to be substituted is maintained. )) fullFag = true } else { println("$$$$$$$$$$ execClass Warning " + attrName + "='" + attrValue + "'") } } } } buflocal.append(">") if(!stackChange.isEmpty){ stackChange.top.getBufChange.append(buflocal) } else { buf.append(buflocal) } if(fullFag == true){ stackChange.top.setStartTagFull(buflocal.toString) } } override def endElement (uri:String , name:String, qualifiedName:String):Unit={ val endTag = "</"+name+">" if(stack.top.equals(name)){ // It is the same as the tag that became a substitution beginning. if(!stackChange.isEmpty) { // Tag to be substituted inside if(stackChange.top.getStartTagDepth == stack.length && name.equals(stackChange.top.getStartTag) && !stackChange.isEmpty) { // Depth of the same stack as tag that became substitution beginning -> tag end stackChange.top.getBufChange.append(endTag) var changeTag:String = "" try{ val execCommand = stackChange.top.getExecCommand var ec:ExecClass = new ExecClass(execCommand(1)) // Object is generated. if(ec != null){ ec.exec("setTag",stackChange.top.getBufChange.toString) // TAG before it substitutes it is set. ec.exec("setParameterMap",pMap) // GetParameterMap method of ServletRequest to acquire parameter if(execCommand.length == 3){ // Argument none changeTag = ec.exec(execCommand(2)).toString }else if(execCommand.length == 4){ // There is one argument. val value = execCommand(3) changeTag = ec.execStr(execCommand(2),execCommand(3)).toString } } } catch { case e:NoSuchMethodException => { println("Exception "+e.getMessage + " NoSuchMethodException!") } case e:Exception => { println("Exception "+e.getMessage + " class or Method not find!") } } var str:String = null if(!stackChange.isEmpty){// Tag inside class="seedo" str = stackChange.top.getStartTagFull + changeTag + endTag } stackChange.pop // The stack for substitution is liberated. if(!stackChange.isEmpty){// class="seedo" stackChange.top.getBufChange.append(str) } else { buf.append(str) // } } else { stackChange.top.getBufChange.append(endTag) } } else { buf.append(endTag) } stack.pop // println("-------------stack.length="+stack.length) } else { println("$$$$$$$$$$ The correspondence of tag is not taken. startTag(stack.top)=" + stack.top + " endTag=" + qualifiedName) } } override def characters(ch:Array[Char],start:Int,length:Int) : Unit = { var str:String = "" for(i <- start to length+start-1){ str += ch(i) } if(!stackChange.isEmpty){// inside tag class="seedo" stackChange.top.getBufChange.append(str) } else { buf.append(str) } } }
package がすべてewsだったので、機能ごとに階層を分ける。
servletから呼び出されるクラスは、package ews.servlet.spに置く。
class htmlSrvは、package ews.servletに置く。
packageの変更により、web.xmlの定義は以下のように修正。
HTMLファイルを置く場所も、テスト用にC:\test_site\htmlに変更する。
この設定を変更すればいろいろなサイトのコンテンツを評価することができます。
またews.servlet.htmlSrvを拡張してファイル転送できるようにしたので、イメージファイルやCSSファイル、JSファイルもこのディレクトリに置くことができます。
web.xml
<servlet> <servlet-name>html</servlet-name> <servlet-class>ews.servlet.htmlSrv</servlet-class> <init-param> <param-name>html</param-name> <param-value>C:\test_site\html</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>html</servlet-name> <url-pattern>/html/*</url-pattern> </servlet-mapping>
コードが落ち着いてきたらソースコード一式をダウンロードできるようにします。
コメントを残す
コメントを投稿するにはログインしてください。