1 package net.sf.saxon.pull; 2 3 import net.sf.saxon.event.PipelineConfiguration; 4 import net.sf.saxon.om.*; 5 import net.sf.saxon.tinytree.TinyNodeImpl; 6 import net.sf.saxon.tinytree.TinyTreeWalker; 7 import net.sf.saxon.trans.XPathException; 8 import net.sf.saxon.type.Type; 9 import net.sf.saxon.value.AtomicValue; 10 11 import javax.xml.transform.SourceLocator ; 12 import java.util.Stack ; 13 14 21 22 public class TreeWalker implements PullProvider, SourceLocator { 23 24 private NodeInfo startNode; 25 private NodeInfo currentNode; 26 private int currentEvent; 27 private Stack iteratorStack = new Stack (); 28 private PipelineConfiguration pipe; 29 30 35 36 public static PullProvider makeTreeWalker(NodeInfo startNode) { 37 if (startNode instanceof UnconstructedParent) { 38 return ((UnconstructedParent)startNode).getPuller(); 39 } 40 if (startNode instanceof TinyNodeImpl) { 41 switch (startNode.getNodeKind()) { 42 case Type.DOCUMENT: 43 case Type.ELEMENT: 44 return new TinyTreeWalker((TinyNodeImpl)startNode); 45 default: 46 return new PullFromIterator(SingletonIterator.makeIterator(startNode)); 47 } 48 49 } else { 50 return new TreeWalker(startNode); 51 } 52 } 53 54 58 59 private TreeWalker(NodeInfo startNode) { 60 this.startNode = startNode; 61 } 62 63 67 68 public void setPipelineConfiguration(PipelineConfiguration pipe) { 69 this.pipe = pipe; 70 } 71 72 75 76 public PipelineConfiguration getPipelineConfiguration() { 77 return pipe; 78 } 79 80 86 87 public int next() throws XPathException { 88 switch(currentEvent) { 89 case START_OF_INPUT: 90 currentNode = startNode; 91 switch (currentNode.getNodeKind()) { 92 case Type.DOCUMENT: 93 currentEvent = START_DOCUMENT; 94 break; 95 case Type.ELEMENT: 96 currentEvent = START_ELEMENT; 97 break; 98 case Type.TEXT: 99 currentEvent = TEXT; 100 break; 101 case Type.COMMENT: 102 currentEvent = COMMENT; 103 break; 104 case Type.PROCESSING_INSTRUCTION: 105 currentEvent = PROCESSING_INSTRUCTION; 106 break; 107 case Type.ATTRIBUTE: 108 currentEvent = ATTRIBUTE; 109 break; 110 case Type.NAMESPACE: 111 currentEvent = NAMESPACE; 112 break; 113 } 114 return currentEvent; 115 116 case START_DOCUMENT: 117 case START_ELEMENT: 118 AxisIterator kids = currentNode.iterateAxis(Axis.CHILD); 119 iteratorStack.push(kids); 120 121 currentNode = (NodeInfo)kids.next(); 122 if (currentNode != null) { 123 switch (currentNode.getNodeKind()) { 124 case Type.ELEMENT: 125 currentEvent = START_ELEMENT; 126 break; 127 case Type.TEXT: 128 currentEvent = TEXT; 129 break; 130 case Type.COMMENT: 131 currentEvent = COMMENT; 132 break; 133 case Type.PROCESSING_INSTRUCTION: 134 currentEvent = PROCESSING_INSTRUCTION; 135 break; 136 } 137 return currentEvent; 138 } else { 139 iteratorStack.pop(); 140 if (iteratorStack.isEmpty()) { 141 currentNode = startNode; 142 } 143 if (currentEvent == START_DOCUMENT) { 144 currentEvent = END_DOCUMENT; 145 } else { 146 currentEvent = END_ELEMENT; 147 } 148 return currentEvent; 149 } 150 case TEXT: 151 case COMMENT: 152 case PROCESSING_INSTRUCTION: 153 case END_ELEMENT: 154 if (iteratorStack.isEmpty()) { 155 if (currentNode == startNode) { 156 currentNode = null; 157 currentEvent = END_OF_INPUT; 158 } else { 159 currentNode = startNode; 160 if (currentNode.getNodeKind() == Type.ELEMENT) { 161 currentEvent = END_ELEMENT; 162 } else { 163 currentEvent = END_DOCUMENT; 164 } 165 } 166 return currentEvent; 167 } 168 do { 169 AxisIterator siblings = (AxisIterator)iteratorStack.peek(); 170 currentNode = (NodeInfo)siblings.next(); 171 if (currentNode == null) { 172 iteratorStack.pop(); 173 if (iteratorStack.isEmpty()) { 174 currentNode = startNode; 175 if (currentNode.getNodeKind() == Type.ELEMENT) { 176 currentEvent = END_ELEMENT; 177 } else { 178 currentEvent = END_DOCUMENT; 179 } 180 return currentEvent; 181 } 182 AxisIterator uncles = (AxisIterator)iteratorStack.peek(); 183 currentNode = (NodeInfo)uncles.current(); 184 if (currentNode.getNodeKind() == Type.DOCUMENT) { 185 currentEvent = END_DOCUMENT; 186 } else { 187 currentEvent = END_ELEMENT; 188 } 189 return currentEvent; 190 } else { 191 switch (currentNode.getNodeKind()) { 192 case Type.ELEMENT: 193 currentEvent = START_ELEMENT; 194 break; 195 case Type.TEXT: 196 currentEvent = TEXT; 197 break; 198 case Type.COMMENT: 199 currentEvent = COMMENT; 200 break; 201 case Type.PROCESSING_INSTRUCTION: 202 currentEvent = PROCESSING_INSTRUCTION; 203 break; 204 } 205 return currentEvent; 206 } 207 } while (true); 208 209 case ATTRIBUTE: 210 case NAMESPACE: 211 case END_DOCUMENT: 212 currentEvent = END_OF_INPUT; 213 return currentEvent; 214 215 case END_OF_INPUT: 216 throw new IllegalStateException ("Cannot call next() when input is exhausted"); 217 218 default: 219 throw new IllegalStateException ("Unrecognized event " + currentEvent); 220 221 } 222 } 223 224 231 232 public int current() { 233 return currentEvent; 234 } 235 236 250 251 public AttributeCollection getAttributes() throws XPathException { 252 if (currentNode.getNodeKind() == Type.ELEMENT) { 253 AttributeCollectionImpl atts = new AttributeCollectionImpl(getNamePool()); 254 SequenceIterator iter = currentNode.iterateAxis(Axis.ATTRIBUTE); 255 while (true) { 256 NodeInfo node = (NodeInfo)iter.next(); 257 if (node == null) { 258 break; 259 } 260 atts.addAttribute(node.getNameCode(), node.getTypeAnnotation(), node.getStringValue(), 0, 0); 261 } 262 return atts; 263 } else { 264 throw new IllegalStateException ("getAttributes() called when current event is not ELEMENT_START"); 265 } 266 } 267 268 287 288 public NamespaceDeclarations getNamespaceDeclarations() throws XPathException { 289 if (currentNode.getNodeKind() == Type.ELEMENT) { 290 if (iteratorStack.size() == 0) { 291 int[] codes = new NamespaceIterator(currentNode, null).getInScopeNamespaceCodes(); 293 return new NamespaceDeclarationsImpl(getNamePool(), codes); 294 } else { 295 return new NamespaceDeclarationsImpl(getNamePool(), currentNode.getDeclaredNamespaces(nsBuffer)); 297 } 298 } 299 throw new IllegalStateException ("getNamespaceDeclarations() called when current event is not ELEMENT_START"); 300 } 301 302 private int[] nsBuffer = new int[10]; 303 304 310 311 public int skipToMatchingEnd() throws XPathException { 312 switch (currentEvent) { 315 case START_DOCUMENT: 316 currentEvent = END_DOCUMENT; 317 return currentEvent; 318 case START_ELEMENT: 319 currentEvent = END_ELEMENT; 320 return currentEvent; 321 default: 322 throw new IllegalStateException ( 323 "Cannot call skipToMatchingEnd() except when at start of element or document"); 324 } 325 } 326 327 334 335 public void close() { 336 } 338 339 344 345 public NamePool getNamePool() { 346 return pipe.getConfiguration().getNamePool(); 347 } 348 349 360 361 public int getNameCode() { 362 return currentNode.getNameCode(); 363 } 364 365 378 379 public int getFingerprint() { 380 return currentNode.getFingerprint(); 381 } 382 383 390 391 public CharSequence getStringValue() throws XPathException { 392 if (currentNode.getNodeKind() == Type.ELEMENT) { 393 skipToMatchingEnd(); 394 } 395 return currentNode.getStringValueCS(); 396 } 397 398 406 407 public int getTypeAnnotation() { 408 return currentNode.getTypeAnnotation(); 409 } 410 411 416 417 public AtomicValue getAtomicValue() { 418 throw new IllegalStateException (); 419 } 420 421 428 429 public SourceLocator getSourceLocator() { 430 return this; 431 } 432 433 444 public String getPublicId() { 445 return null; 446 } 447 448 462 public String getSystemId() { 463 return currentNode.getSystemId(); 464 } 465 466 481 public int getLineNumber() { 482 return currentNode.getLineNumber(); 483 } 484 485 500 public int getColumnNumber() { 501 return -1; 502 } 503 } 504 505 | Popular Tags |