PageRenderTime 153ms CodeModel.GetById 120ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 1ms

/bundles/plugins-trunk/XML/xml/parser/javacc/XmlCollector.java

#
Java | 169 lines | 114 code | 26 blank | 29 comment | 19 complexity | cf4010c2c2579620e6e67048ee32287e MD5 | raw file
  1/*
  2* XmlCollector.java -- structures an HTML document tree.  
  3* Copyright (C) 1999 Quiotix Corporation.  
  4*
  5* This program is free software; you can redistribute it and/or modify
  6* it under the terms of the GNU General Public License, version 2, as 
  7* published by the Free Software Foundation.  
  8*
  9* This program is distributed in the hope that it will be useful,
 10* but WITHOUT ANY WARRANTY; without even the implied warranty of
 11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12* GNU General Public License (http://www.gnu.org/copyleft/gpl.txt)
 13* for more details.
 14*/
 15
 16package xml.parser.javacc;
 17
 18import java.io.FileInputStream;
 19import java.io.InputStream;
 20import java.util.*;
 21
 22/**
 23 * An XmlVisitor which modifies the structure of the document so that
 24 * begin tags are matched properly with end tags and placed in TagBlock
 25 * elements.  Typically, an XmlDocument is created by the parser, which
 26 * simply returns a flat list of elements.  The XmlCollector takes this
 27 * flat list and gives it the structure that is implied by the HTML content.
 28 *
 29 * @author Brian Goetz, Quiotix
 30 */
 31
 32public class XmlCollector extends XmlVisitor {
 33
 34    protected ElementStack tagStack = new ElementStack();
 35    protected ElementStack elements;
 36    protected boolean collected;
 37
 38    private static class TagStackEntry {
 39        String tagName;
 40        int index;
 41    }
 42
 43    private static class ElementStack extends Vector {
 44        ElementStack() {
 45            super();
 46        }
 47
 48        ElementStack( int n ) {
 49            super( n );
 50        }
 51
 52        public void popN( int n ) {
 53            elementCount -= n;
 54        }
 55    }
 56
 57    protected int pushNode( XmlDocument.XmlElement e ) {
 58        if (e != null) {
 59            elements.addElement( e );
 60        }
 61        return elements.size() - 1;
 62    }
 63                                                             
 64    public void visit( XmlDocument.Comment c ) {
 65            pushNode( c );
 66    }
 67
 68    public void visit( XmlDocument.Text t ) {
 69        pushNode( t );
 70    }
 71
 72    public void visit( XmlDocument.Newline n ) {
 73        pushNode( n );
 74    }
 75
 76    public void visit( XmlDocument.Tag t ) {
 77        if (t == null) {
 78            return;   
 79        }
 80        TagStackEntry ts = new TagStackEntry();
 81        int index;
 82
 83        /* Push the tag onto the element stack, and push an entry on the tag
 84        stack if it's a tag we care about matching */
 85        index = pushNode( t );
 86        if ( !t.emptyTag ) {
 87            ts.tagName = t.tagName;
 88            ts.index = index;
 89            tagStack.addElement( ts );
 90        }
 91    }
 92
 93    public void visit( XmlDocument.EndTag t ) {
 94        if (t == null)
 95            return;
 96        int i;
 97        for ( i = tagStack.size() - 1; i >= 0; i-- ) {
 98            TagStackEntry ts = ( TagStackEntry ) tagStack.elementAt( i );
 99            if ( t.tagName.equals( ts.tagName ) ) {
100                XmlDocument.TagBlock block;
101                XmlDocument.ElementSequence blockElements;
102                XmlDocument.Tag tag;
103
104                // Create a new ElementSequence and copy the elements to it
105                blockElements = new XmlDocument.ElementSequence( elements.size() - ts.index - 1 );
106                for ( int j = ts.index + 1; j < elements.size(); j++ ) {
107                    blockElements.addElement( ( XmlDocument.XmlElement ) elements.elementAt( j ) );
108                }
109                tag = ( XmlDocument.Tag ) elements.elementAt( ts.index );
110                block = new XmlDocument.TagBlock( tag, blockElements, t );
111                block.setStartLocation( tag.getStartLocation() );
112                block.setEndLocation( t.getEndLocation() );
113
114                // Pop the elements off the stack, push the new block
115                elements.popN( elements.size() - ts.index );
116                elements.addElement( block );
117
118                // Pop the matched tag and intervening unmatched tags
119                tagStack.popN( tagStack.size() - i );
120
121                collected = true;
122                break;
123            }
124        }
125
126        // If we didn't find a match, just push the end tag
127        if ( i < 0 )
128            pushNode( t );
129    }
130
131    public void visit( XmlDocument.TagBlock bl ) {
132        if (bl == null)
133            return;
134        XmlCollector c = new XmlCollector();
135        c.start();
136        c.visit( bl.body );
137        c.finish();
138        pushNode( bl );
139    }
140
141    public void visit( XmlDocument.ElementSequence s ) {
142        if ( s == null )
143            return ;
144        elements = new ElementStack( s.size() );
145        collected = false;
146
147        for ( Iterator iterator = s.iterator(); iterator.hasNext(); ) {
148            XmlDocument.XmlElement htmlElement = ( XmlDocument.XmlElement ) iterator.next();
149            if ( htmlElement != null )
150                htmlElement.accept( this );
151        }
152        if ( collected )
153            s.setElements( elements );
154    }
155
156    public static void main( String[] args ) throws Exception {
157        InputStream r = new FileInputStream( args[ 0 ] );
158
159        try {
160            XmlDocument document = new XmlParser( r ).XmlDocument();
161            document.accept( new XmlScrubber() );
162            document.accept( new XmlCollector() );
163            document.accept( new XmlDumper( System.out ) );
164        }
165        finally {
166            r.close();
167        }
168    }
169}