<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    lycong

    使用SAX對XML根據(jù)具體需求過濾標(biāo)簽和長度截取

           需要解決的問題是 根據(jù)一輸入流讀取一段XML內(nèi)容,然后對其進(jìn)行過濾截取,最后寫回輸出流中。具體說明如下:
    1.對XML根據(jù)特定需求,過濾標(biāo)簽(如SCRIPT,FRAME等非標(biāo)準(zhǔn)HTML標(biāo)簽),過濾屬性(如onclick,onblur等)
    2.對XML進(jìn)行長度截取,具體做法如下:
    (1)對start標(biāo)簽的處理: 若加上start標(biāo)簽長度后超過最大允許長度,則去除該標(biāo)簽,且同時(shí)去除后面和該標(biāo)簽同一等級的所有標(biāo)簽。
    (2)對text內(nèi)容的處理:若加上text內(nèi)容的長度后超過最大允許的長度,則從中截取text長度,并加上省略號......
    (3)對end標(biāo)簽內(nèi)容的處理:不做長度截取,且要做到自動(dòng)補(bǔ)齊end標(biāo)簽。

            有關(guān)SAX的詳細(xì)介紹,請查看最好的參考資料 http://www.saxproject.org/ 。其中有一個(gè)很重要的類 DefaultHandler, 該類中的startElement, endElement, characters 3個(gè)方法尤為重要。 為解決上述問題,需要設(shè)計(jì)2個(gè)類:HTMLWriter, HTMLFilter, 其中HTMLFilter是HTMLWriter的子類,HTMLWriter繼承了DefaultHandler,其中最為關(guān)鍵的是要重寫上述3個(gè)關(guān)鍵方法。

    一.HTMLWriter類的代碼:
    這個(gè)類主要用于寫操作,最重要是理解變量strippedElementLevel 的用法。上面問題的具體業(yè)務(wù)邏輯處理(標(biāo)簽的過濾和長度截取)將在子類HTMLFilter 解決。
    package org.util.sax.html

    import openxml.parser.HTMLdtd;
    import openxml.parser.HTMLSAXParser;
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.InputSource;
    import org.xml.sax.XMLReader;
    import org.xml.sax.ErrorHandler;
    import org.xml.sax.ext.LexicalHandler;
    import org.xml.sax.helpers.DefaultHandler;

    import java.io.*;




    public class HTMLWriter extends DefaultHandler implements LexicalHandler {

        
    private ErrorHandler errorHandler;

        
    private Writer out;

        
    private int strippedElementLevel = 0; //用來作為start標(biāo)簽和end標(biāo)簽成對出現(xiàn)的標(biāo)記(極為重要),具體算法思路類似于堆棧
        
    private boolean inRawElement;


        
    public void filter(String htmlContent) throws IOException, SAXException {
            filter(
    new StringReader(htmlContent));
        }


        
    public void filter(Reader in) throws IOException, SAXException {
            filter(
    new InputSource(in));
        }


        
    public void filter(InputSource in) throws IOException, SAXException {
            HTMLSAXParser parser 
    = new HTMLSAXParser(errorHandler, false);
            parser.setLexicalHandler(
    this);

            XMLReader htmlReader 
    = new HTMLParserAdapter(parser);
            htmlReader.setFeature(
    "http://xml.org/sax/features/namespaces"false);
            htmlReader.setContentHandler(
    this);

            prepare();
            htmlReader.parse(in);
        }



        
    protected void prepare() {
            
    if (out == null{
                out 
    = new StringWriter();
            }

        }



        
    public void setErrorHandler(ErrorHandler errorHandler) {
            
    this.errorHandler = errorHandler;
        }


        
    public void setOut(Writer out) {
            
    this.out = out;
        }


        
    public Writer getOut() {
            
    return out;
        }


        
    public String getResultAsString() {
            
    if (out instanceof StringWriter) {
                
    return out.toString();
            }

            
    throw new IllegalStateException("Not a buffered target");
        }



        @Override
        
    public void startDocument() throws SAXException {
            prepare();
        }



        @Override
        
    public final void startElement(String namespaceURI,
                                 String localName,
                                 String qName,
                                 Attributes attrs) 
    throws SAXException {
            
    if (strippedElementLevel > 0{
                strippedElementLevel
    ++;
                
    return;
            }


            
    // features/namespace is false
            if (!startTag(qName, attrs)) {
                strippedElementLevel 
    = 1;
            }

        }



        @Override
        
    public final void endElement(String namespaceURI,
                                     String localName,
                                     String qName) 
    throws SAXException {
            
    if (strippedElementLevel > 0{
                strippedElementLevel
    --;
                
    return;
            }


            
    // features/namespace is false
            endTag(qName);
        }



        
    protected boolean startTag(String tagName, Attributes attrs) throws SAXException {

            String tagUpper 
    = tagName.toUpperCase();

            inRawElement 
    = "SCRIPT".equals(tagUpper) || "STYLE".equals(tagUpper);

            write(
    '<');
            write(tagName);
            
    for (int i = 0; i < attrs.getLength(); i++{
                
    // features/namespace is false
                String attrName = attrs.getQName(i);
                attribute(tagUpper, attrName.toLowerCase(), attrName, attrs.getValue(i));
            }

            write(
    '>');

            
    return true;
        }



        
    protected void endTag(String tagName) throws SAXException {
            inRawElement 
    = false;
            
    if (!isEmptyTag(tagName.toUpperCase())) {
                write(
    "</");
                write(tagName);
                write(
    '>');
            }

        }



        @Override
        
    public  void characters(char[] ch, int start, int length) throws SAXException {
            
    if (strippedElementLevel != 0{
                
    return;
            }


            
    if (inRawElement) {
                write(ch, start, length);
                
    return;
            }


            text(ch, start, length);
        }



        
    protected void text(char[] ch, int start, int length) throws SAXException {
            writeText(ch, start, length);
        }



        
    public void startDTD(String tagName, String publicId, String systemId) throws SAXException {
            write(
    "<!DOCTYPE ");
            write(tagName);
            write(
    " PUBLIC ");
            write(
    '"');
            write(publicId);
            write(
    '"');
            write(
    '>');
        }



        
    public void endDTD() {}
        
    public void startEntity(String name) {}
        
    public void endEntity(String name) {}
        
    public void startCDATA() {}
        
    public void endCDATA() {}

        
    public void comment(char ch[], int start, int length) throws SAXException {
            
    /*
            if (strippedElementLevel == 0) {
                write("<!--");
                write(ch, start, length);
                write("-->");
            }
            
    */

        }



        @Override
        
    public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
            
    if (strippedElementLevel == 0{
                write(ch, start, length);
            }

        }



        
    protected void attribute(final String tagUpper,  // 規(guī)范化的 TAG  名稱 - 使用大寫字母
                                 final String attrLower, // 規(guī)范化的 屬性 名稱 - 使用小寫字母
                                 String attrName,
                                 String attrValue) 
    throws SAXException {
            write(
    ' ');
            write(attrName);
            
    if (!isBoolean(attrLower, tagUpper)) {
                write(
    '=');
                write(
    '"');
                
    for (int i = 0; i < attrValue.length(); i++{
                    writeEncoded(attrValue.charAt(i), 
    true);
                }

                write(
    '"');
            }

        }



        
    protected final void writeText(char[] ch, int start, int length) throws SAXException {
            writeTextWithEnd(ch, start, start 
    + length);
        }



        
    protected final void writeTextWithEnd(char[] ch, int begin, int end) throws SAXException {
            
    for (int i = begin; i < end; i++{
                writeEncoded(ch[i], 
    false);
            }

        }



        
    protected void writeEncoded(char c, boolean isAttr) throws SAXException {
            
    switch (c) {
            
    case '<':
                write(
    "&lt;");
                
    break;
            
    case '>':
                write(
    "&gt;");
                
    break;
            
    case '&':
                write(
    "&amp;");
                
    break;
            
    case 0xa0// NBSP
                
    // 暫時(shí)只特殊處理特殊字符 NBSP
                
    // 當(dāng)組信 NBSP 在轉(zhuǎn)換到純文本時(shí)可變成空格
                
    // 但其它特殊字符沒有簡單的Ascii字符可替代, 因而這里也不執(zhí)行替代
                write("&nbsp;");
                
    break;
            
    case '"':
                
    if (isAttr) {
                    write(
    "&quot;");
                    
    break;
                }

            
    default:
                write(c);
            }

        }


        
    protected  void write(char c) throws SAXException {
            
    try {
                out.write(c);
            }
     catch (IOException e) {
                
    throw new SAXException(e);
            }

        }



        
    protected  void write(char ch[], int start, int length) throws SAXException {
            
    try {
                out.write(ch, start, length);
            }
     catch (IOException e) {
                
    throw new SAXException(e);
            }

        }


        
    protected  void write(String s) throws SAXException {
            
    try {
                out.write(s);
            }
     catch (IOException e) {
                
    throw new SAXException(e);
            }

        }



        
    private static boolean isBoolean(String attrLower, String tagUpper) {
            
    return HTMLdtd.isBoolean(attrLower, tagUpper);
        }


        
    private static boolean isEmptyTag(String tagUpper) {
            
    return HTMLdtd.isEmptyTag(tagUpper);
        }


    }


    二. HTMLFilter 類的代碼:
    主要解決標(biāo)簽過濾,即哪些標(biāo)簽和屬性需要過濾,解決長度截取問題,即斷點(diǎn)出現(xiàn)在startTag,text,endTag的情況應(yīng)該如何解決。
    主要理解重寫父類HTMLWriter的幾個(gè)方法:startTag(),characters(),comment(),attribute(), 另外需要一個(gè)成員變量currentLen記錄當(dāng)前寫入的長度,在進(jìn)行write()方法時(shí)要對currentLen變量進(jìn)行疊加。

    package org.util.sax.html;

    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;

    import java.util.Map;
    import java.io.Writer;
    import java.io.CharArrayWriter;
    import java.io.IOException;

    public class HTMLFilter extends HTMLWriter {

        ConfigManager conf 
    = CM.getConfig();
        Map
    <String, String> cidMap;    //cid 和 正文內(nèi)容圖片 filename的 映射
            
        
    private int currentLen; //當(dāng)前已經(jīng)寫入out的長度
        private int maxLen; //允許push的最大長度
        private boolean ignore=false//當(dāng)出現(xiàn)要截取時(shí),就設(shè)為 true ,意味著如果ignore 為true時(shí), 就以后的內(nèi)容都要忽略。
        

        
    public HTMLFilter(Map<String,String> map,int allowMessage_BodyLen) {
            
    //super.setAllowContentLen(allowMessage_BodyLen);
            this.maxLen=allowMessage_BodyLen;
            
    this.cidMap=map;
        }


        @Override
        
    protected boolean startTag(String tagName, Attributes attrs) throws SAXException {
            
    if (!isTagAllowed(tagName, attrs)) {
                
    return false;
            }


            
    if (ignore) {
                
    return false;
            }


            Writer originalOutput 
    = getOut();
            
    int remainChars = getRemainChars();

            
    if(remainChars == 0){
                ignore 
    = true;
                write(
    "");
                
    return false;
            }


            CharArrayWriter capturedOutput 
    = new CharArrayWriter();
            setOut(capturedOutput);

            
    try {
                
    if (super.startTag(tagName, attrs)) {
                    
    if (capturedOutput.toCharArray().length < remainChars) {
                        
    try {
                            originalOutput.write(capturedOutput.toCharArray());
                            
    return true;
                        }
     catch (IOException e) {
                            
    throw new SAXException(e);
                        }

                    }
                    
                }

            }
     finally {
               setOut(originalOutput);
            }


            ignore 
    = true;
            write(
    "");
            
    return false;
            
        }



        @Override
        
    public  void characters(char[] ch, int start, int length) throws SAXException {
            
    if (ignore) {      //如果長度已經(jīng)超出限制,則不寫
                return;
            }

            
    int remainChars = getRemainChars();

            
    if (remainChars == 0{
                ignore 
    = true;
                write(
    "");
                
    return;
            }


            
    if (remainChars < length) {       //當(dāng)將要寫入的 text 長度  大于 remainChars 時(shí), 就寫入所能夠?qū)懭氲淖址缓筇砑邮÷蕴?img src="http://www.tkk7.com/Images/dot.gif" alt="" />
                ignore = true;
                
    super.characters(ch, start, remainChars);
                write(
    "");
            }
     else {
                
    super.characters(ch, start, length);
            }

        }


        @Override
        
    protected void endTag(String tagName) throws SAXException {
            
    super.endTag(tagName);
        }


        
    public void comment(char ch[], int start, int length) throws SAXException{
            
    if(ignore){
                
    return;
            }

            
    int remainChars = getRemainChars();

            
    if (remainChars == 0{
                ignore 
    = true;
                write(
    "");
                
    return;
            }

            
    if (remainChars < length) {
                ignore
    =true;
                
    super.comment(ch, start, remainChars);
                
            }
     else {
                
    super.comment(ch, start, length);
            }


        }


        @Override
        
    protected void attribute(final String tagUpper,
                                 
    final String attrLower,
                                 
    final String attrName,
                                 String attrValue) 
    throws SAXException {

            
    if (attrLower.startsWith("on")) {
                
    return;
            }

            
    if (tagUpper.equalsIgnoreCase("IMG"&& attrLower.equalsIgnoreCase("src"&& attrValue.trim().indexOf("cid:"!= -1{
                attrValue
    =attrValue.trim();
                
    int cid_idx = attrValue.indexOf("cid:");
                String cid 
    = attrValue.substring(cid_idx + 4);
               
    // System.out.println("cid is: "+ cid);
                String photoName = cidMap.get(cid);
               
    // System.out.println("photoName is: "+ photoName);
                if (photoName != null{
                    
    super.attribute(tagUpper, attrLower, attrName, "#{" + photoName + "}");
                }
     else{
                    
    super.attribute(tagUpper, attrLower, attrName, "#{" + " " + "}");
                }



            }
     else {
                attrValue 
    = transformScript(attrValue);
                
    super.attribute(tagUpper, attrLower, attrName, attrValue);
            }

        }


        
    private String transformScript(final String data) {
            
    if (true{
                
    final String trimedData = data.trim();
                
    final String scriptData = mySubstringAfterIgnoreCase(trimedData, "javascript:");
                
    if (scriptData != null{
                    
    return "";
                }

            }

            
    return data;
        }


        
    protected boolean isTagAllowed(String tagName, Attributes attrs) {
            
    if (tagName.equalsIgnoreCase("SCRIPT")) {
                
    return false;
            }

            
    if(tagName.equalsIgnoreCase("A")){    //超鏈接標(biāo)簽不push
                return false;
            }

            
    if (tagName.equalsIgnoreCase("PARAM")) {
                String name 
    = getAttrIgnoreCase(attrs, "name");
                
    if ("movie".equalsIgnoreCase(name) || "src".equalsIgnoreCase(name)) {
                    
    return false;
                }

            }

            
    /*
            if (tagName.equalsIgnoreCase("STYLE")) {
                return false;
            }
            
    */

            
    if (tagName.equalsIgnoreCase("LINK"&&
                    
    "stylesheet".equalsIgnoreCase(getAttrIgnoreCase(attrs, "rel"))) {
                
    return false;
            }

            
    if (tagName.equals("FRAME"|| tagName.equals("FRAMESET")) {
                
    return false;
            }

            
    return true;
        }



        
    private static String getAttrIgnoreCase(Attributes attrs, String name) {
            
    for (int i = 0, len = attrs.getLength(); i < len; i++{
                
    if (name.equalsIgnoreCase(attrs.getQName(i))) {
                    
    return attrs.getValue(i);
                }

            }

            
    return null;
        }



        
    /**
         * 忽略控制字符后, 判斷是否以某字符串開始, 并返回匹配后的截取部分.
         * <p/>
         * <p/>
         * 注: 忽略控制字符是為了對付IE的安全漏洞
         *
         * 
    @param source 源字符串
         * 
    @param prefix 要匹配的前綴字符串
         * 
    @return 如果測試成功, 返回截取后的字符串; 否則, 返回 null;
         
    */

        
    static String mySubstringAfterIgnoreCase(String source, String prefix) {
            
    int sourceLength = source.length();
            
    int targetLength = prefix.length();

            
    if (sourceLength < targetLength) {
                
    return null;
            }


            
    int sourceOffset = 0;
            
    int targetOffset = 0;
            
    char targetChar = Character.toUpperCase(prefix.charAt(targetOffset));

            
    for (; sourceOffset < sourceLength; sourceOffset++{
                
    char c = source.charAt(sourceOffset);
                
    if (c < ' '{
                    
    // 忽略控制字符
                    continue;
                }


                
    if (Character.toUpperCase(c) != targetChar) {
                    
    break;
                }


                targetOffset
    ++;
                
    if (targetOffset == targetLength) {
                    
    return source.substring(sourceOffset + 1);
                }


                targetChar 
    = Character.toUpperCase(prefix.charAt(targetOffset));
            }


            
    return null;
        }


        
    protected void write(char c) throws SAXException {
            
    super.write(c);
            currentLen
    ++;
        }


        
        
    protected void write(char ch[], int start, int length) throws SAXException {
            
    super.write(ch, start, length);
            currentLen 
    += length;
        }


        
        
    protected  void write(String s) throws SAXException {
            
    super.write(s);
            currentLen 
    += s.length();
        }


         
    protected int getRemainChars(){        //求出還剩多少個(gè)字符可以寫入
            return (maxLen - currentLen);
        }



    }




     

    posted on 2008-09-01 21:26 cong 閱讀(927) 評論(0)  編輯  收藏 所屬分類: JAVA


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     

    My Links

    Blog Stats

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 99re6在线视频精品免费下载| 亚洲成人午夜在线| 色婷婷综合缴情综免费观看 | 亚洲国产精品专区在线观看| 日本亚洲欧美色视频在线播放| 日韩激情淫片免费看| 亚洲精品无播放器在线播放 | 特级毛片免费播放| 免费人成在线观看网站视频 | 色影音免费色资源| 亚洲人成人77777网站不卡| 国产精品久久免费| 亚洲色无码国产精品网站可下载| 成人免费看片又大又黄| 亚洲精品色播一区二区| 国产三级免费观看| 一级片在线免费看| 亚洲欧洲成人精品香蕉网| 亚洲人成网亚洲欧洲无码久久| 黄视频在线观看免费| 亚洲日产无码中文字幕| 日韩免费的视频在线观看香蕉| 亚洲爆乳无码专区| 91精品全国免费观看含羞草| 亚洲妓女综合网99| 成人看的午夜免费毛片| 亚洲精品9999久久久久无码| 免费人成在线观看视频播放| 中文字幕不卡高清免费| 亚洲成在人天堂在线| 国产国产人免费视频成69堂| 亚洲成年网站在线观看| 日本免费高清一本视频| 男女猛烈无遮掩视频免费软件| 亚洲中文字幕在线观看| 日韩内射激情视频在线播放免费| 亚洲国产精品久久网午夜| 全免费一级午夜毛片| 日本黄页网址在线看免费不卡| 亚洲国产无套无码av电影| 222www免费视频|