KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nwalsh > saxon > UnwrapLinksEmitter


1 package com.nwalsh.saxon;
2
3 import java.util.Stack JavaDoc;
4 import org.xml.sax.*;
5 import org.w3c.dom.*;
6 import javax.xml.transform.TransformerException JavaDoc;
7 import com.icl.saxon.output.*;
8 import com.icl.saxon.om.*;
9 import com.icl.saxon.Controller;
10 import com.icl.saxon.tree.AttributeCollection;
11
12 /**
13  * <p>Saxon extension to unwrap links in a result tree fragment.</p>
14  *
15  * <p>$Id: UnwrapLinksEmitter.java,v 1.1 2002/06/26 11:02:05 nwalsh Exp $</p>
16  *
17  * <p>Copyright (C) 2000, 2002 Norman Walsh.</p>
18  *
19  * <p>This class provides the guts of a
20  * <a HREF="http://saxon.sf.net/">Saxon 6.*</a>
21  * implementation of a link unwrapper.</p>
22  *
23  * <p>The general design is this: the stylesheets construct a result tree
24  * fragment for some environment. Then the result tree fragment
25  * is "replayed" through the UnwrapLinksEmitter; the UnwrapLinksEmitter
26  * builds a
27  * new result tree fragment from this event stream with top-level links unwrapped.
28  * That RTF is returned. Note that only a <i>single</i> level of unwrapping
29  * is performed. This is clearly a crude implementation.
30  * </p>
31  *
32  * <p><b>Change Log:</b></p>
33  * <dl>
34  * <dt>1.0</dt>
35  * <dd><p>Initial release.</p></dd>
36  * </dl>
37  *
38  * @author Norman Walsh
39  * <a HREF="mailto:ndw@nwalsh.com">ndw@nwalsh.com</a>
40  *
41  * @version $Id: UnwrapLinksEmitter.java,v 1.1 2002/06/26 11:02:05 nwalsh Exp $
42  *
43  */

44 public class UnwrapLinksEmitter extends CopyEmitter {
45   /** A stack for the preserving information about open elements. */
46   protected Stack JavaDoc elementStack = null;
47   protected Stack JavaDoc saveStack = null;
48
49   /** The FO namespace name. */
50   protected static String JavaDoc foURI = "http://www.w3.org/1999/XSL/Format";
51
52   /** The XHTML namespace name. */
53   protected static String JavaDoc xhURI = "http://www.w3.org/1999/xhtml";
54
55   /** Is the stylesheet currently running an FO stylesheet? */
56   protected boolean foStylesheet = false;
57
58   /** Are we currently in a link? How deep? */
59   protected int linkDepth = 0;
60   protected int skipDepth = 0;
61
62   protected int htmlAFingerprint = 0;
63   protected int xhtmlAFingerprint = 0;
64   protected boolean inSkip = false;
65   protected boolean tryAgain = false;
66
67
68   /** <p>Constructor for the UnwrapLinksEmitter.</p>
69    *
70    * @param namePool The name pool to use for constructing elements and attributes.
71    * @param foStylesheet Is this an FO stylesheet?
72    */

73   public UnwrapLinksEmitter(Controller controller,
74                 NamePool namePool,
75                 boolean foStylesheet) {
76     super(controller,namePool);
77     elementStack = new Stack JavaDoc();
78     this.foStylesheet = foStylesheet;
79
80     htmlAFingerprint = namePool.getFingerprint("", "a");
81     xhtmlAFingerprint = namePool.getFingerprint(xhURI, "a");
82   }
83
84   /** Process start element events. */
85   public void startElement(int nameCode,
86                org.xml.sax.Attributes JavaDoc attributes,
87                int[] namespaces,
88                int nscount)
89     throws TransformerException JavaDoc {
90
91     int thisFingerprint = namePool.getFingerprint(nameCode);
92     boolean isLink = (thisFingerprint == htmlAFingerprint
93               || thisFingerprint == xhtmlAFingerprint);
94
95     if (isLink) {
96       linkDepth++;
97       tryAgain = tryAgain || inSkip;
98     }
99
100     if (isLink && linkDepth > 1 && !inSkip) {
101       inSkip = true;
102
103       // Close all the open elements
104
saveStack = new Stack JavaDoc();
105       Stack JavaDoc tempStack = new Stack JavaDoc();
106       while (!elementStack.empty()) {
107     StartElementInfo elem = (StartElementInfo) elementStack.pop();
108     rtfEmitter.endElement(elem.getNameCode());
109     saveStack.push(elem);
110     tempStack.push(elem);
111       }
112
113       while (!tempStack.empty()) {
114     StartElementInfo elem = (StartElementInfo) tempStack.pop();
115     elementStack.push(elem);
116       }
117     }
118
119     if (inSkip) {
120       skipDepth++;
121     } else {
122     }
123
124     rtfEmitter.startElement(nameCode,attributes,namespaces,nscount);
125
126     StartElementInfo sei = new StartElementInfo(nameCode, attributes,
127                         namespaces, nscount);
128     elementStack.push(sei);
129   }
130
131   /** Process end element events. */
132   public void endElement(int nameCode) throws TransformerException JavaDoc {
133     int thisFingerprint = namePool.getFingerprint(nameCode);
134     boolean isLink = (thisFingerprint == htmlAFingerprint
135               || thisFingerprint == xhtmlAFingerprint);
136
137     rtfEmitter.endElement(nameCode);
138     elementStack.pop();
139
140     if (isLink) {
141       linkDepth--;
142     }
143
144     if (inSkip) {
145       skipDepth--;
146       inSkip = (skipDepth > 0);
147       if (!inSkip) {
148     // Reopen all the ones we closed before...
149
while (!saveStack.empty()) {
150       StartElementInfo elem = (StartElementInfo) saveStack.pop();
151
152       AttributeCollection attr = (AttributeCollection)elem.getAttributes();
153       AttributeCollection newAttr = new AttributeCollection(namePool);
154
155       for (int acount = 0; acount < attr.getLength(); acount++) {
156         String JavaDoc localName = attr.getLocalName(acount);
157         String JavaDoc type = attr.getType(acount);
158         String JavaDoc value = attr.getValue(acount);
159         String JavaDoc uri = attr.getURI(acount);
160         String JavaDoc prefix = "";
161
162         if (localName.indexOf(':') > 0) {
163           prefix = localName.substring(0, localName.indexOf(':'));
164           localName = localName.substring(localName.indexOf(':')+1);
165         }
166
167         if (uri.equals("")
168         && ((foStylesheet
169              && localName.equals("id"))
170             || (!foStylesheet
171             && (localName.equals("id")
172                 || localName.equals("name"))))) {
173           // skip this attribute
174
} else {
175           newAttr.addAttribute(prefix, uri, localName, type, value);
176         }
177       }
178
179       rtfEmitter.startElement(elem.getNameCode(),
180                   newAttr,
181                   elem.getNamespaces(),
182                   elem.getNSCount());
183     }
184       }
185     }
186   }
187
188   public boolean tryAgain()
189     throws TransformerException JavaDoc {
190     return tryAgain;
191   }
192
193   /**
194    * <p>A private class for maintaining the information required to call
195    * the startElement method.</p>
196    *
197    * <p>In order to close and reopen elements, information about those
198    * elements has to be maintained. This class is just the little record
199    * that we push on the stack to keep track of that info.</p>
200    */

201   private class StartElementInfo {
202     private int _nameCode;
203     org.xml.sax.Attributes JavaDoc _attributes;
204     int[] _namespaces;
205     int _nscount;
206
207     public StartElementInfo(int nameCode,
208                 org.xml.sax.Attributes JavaDoc attributes,
209                 int[] namespaces,
210                 int nscount) {
211       _nameCode = nameCode;
212       _attributes = attributes;
213       _namespaces = namespaces;
214       _nscount = nscount;
215     }
216
217     public int getNameCode() {
218       return _nameCode;
219     }
220
221     public org.xml.sax.Attributes JavaDoc getAttributes() {
222       return _attributes;
223     }
224
225     public int[] getNamespaces() {
226       return _namespaces;
227     }
228
229     public int getNSCount() {
230       return _nscount;
231     }
232   }
233 }
234
Popular Tags