148 private NGCCEventReceiver currentHandler; 149 150 public int replace( NGCCEventReceiver o, NGCCEventReceiver n ) { 151 if(o!=currentHandler) 152 throw new IllegalStateException(); // bug of RelaxNGCC 153 currentHandler = n; 154 155 return 0; // we only have one thread. 156 } 157 158 /** 159 * Processes buffered text. 160 * 161 * This method will be called by the start/endElement event to process 162 * buffered text as a text event. 163 * 164 * <p> 165 * Whitespace handling is a tricky business. Consider the following 166 * schema fragment: 167 * 168 * <xmp> 169 * <element name="foo"> 170 * <choice> 171 * <element name="bar"><empty/></element> 172 * <text/> 173 * </choice> 174 * </element> 175 * </xmp> 176 * 177 * Assume we hit the following instance: 178 * <xmp> 179 * <foo> <bar/></foo> 180 * </xmp> 181 * 182 * Then this first space needs to be ignored (for otherwise, we will 183 * end up treating this space as the match to <text/> and won't 184 * be able to process <bar>.) 185 * 186 * Now assume the following instance: 187 * <xmp> 188 * <foo/> 189 * </xmp> 190 * 191 * This time, we need to treat this empty string as a text, for 192 * otherwise we won't be able to accept this instance. 193 * 194 * <p> 195 * This is very difficult to solve in general, but one seemingly 196 * easy solution is to use the type of next event. If a text is 197 * followed by a start tag, it follows from the constraint on 198 * RELAX NG that that text must be either whitespaces or a match 199 * to <text/>. 200 * 201 * <p> 202 * On the contrary, if a text is followed by a end tag, then it 203 * cannot be whitespace unless the content model can accept empty, 204 * in which case sending a text event will be harmlessly ignored 205 * by the NGCCHandler. 206 * 207 * <p> 208 * Thus this method take one parameter, which controls the 209 * behavior of this method. 466 ); 467 468 redirect.startElement(uri,local,qname,currentAtts); 469 redirectionDepth=1; 470 } 471 472 // 473 // 474 // validation context implementation 475 // 476 // 477 /** in-scope namespace mapping. 478 * namespaces[2n ] := prefix 479 * namespaces[2n+1] := namespace URI */ 480 private final ArrayList namespaces = new ArrayList(); 481 /** 482 * Index on the namespaces array, which points to 483 * the top of the effective bindings. Because of the 484 * timing difference between the startPrefixMapping method 485 * and the execution of the corresponding actions, 486 * this value can be different from <code>namespaces.size()</code>. 487 * <p> 488 * For example, consider the following schema: 489 * <pre><xmp> 490 * <oneOrMore> 491 * <element name="foo"><empty/></element> 492 * </oneOrMore> 493 * code fragment X 494 * <element name="bob"/> 495 * </xmp></pre> 496 * Code fragment X is executed after we see a startElement event, 497 * but at this time the namespaces variable already include new 498 * namespace bindings declared on "bob". 499 */ 500 private int nsEffectivePtr=0; 501 502 /** 503 * Stack to preserve old nsEffectivePtr values. 504 */ 505 private final Stack nsEffectiveStack = new Stack(); 506 507 public String resolveNamespacePrefix( String prefix ) { 508 for( int i = nsEffectivePtr-2; i>=0; i-=2 ) 509 if( namespaces.get(i).equals(prefix) ) 510 return (String)namespaces.get(i+1); 511 512 // no binding was found. 513 if(prefix.equals("")) return ""; // return the default no-namespace 514 if(prefix.equals("xml")) // pre-defined xml prefix 515 return "http://www.w3.org/XML/1998/namespace"; | 148 private NGCCEventReceiver currentHandler; 149 150 public int replace( NGCCEventReceiver o, NGCCEventReceiver n ) { 151 if(o!=currentHandler) 152 throw new IllegalStateException(); // bug of RelaxNGCC 153 currentHandler = n; 154 155 return 0; // we only have one thread. 156 } 157 158 /** 159 * Processes buffered text. 160 * 161 * This method will be called by the start/endElement event to process 162 * buffered text as a text event. 163 * 164 * <p> 165 * Whitespace handling is a tricky business. Consider the following 166 * schema fragment: 167 * 168 * <pre>{@code 169 * <element name="foo"> 170 * <choice> 171 * <element name="bar"><empty/></element> 172 * <text/> 173 * </choice> 174 * </element> 175 * }</pre> 176 * 177 * Assume we hit the following instance: 178 * <pre>{@code 179 * <foo> <bar/></foo> 180 * }</pre> 181 * 182 * Then this first space needs to be ignored (for otherwise, we will 183 * end up treating this space as the match to <text/> and won't 184 * be able to process <bar>.) 185 * 186 * Now assume the following instance: 187 * <pre>{@code 188 * <foo/> 189 * }</pre> 190 * 191 * This time, we need to treat this empty string as a text, for 192 * otherwise we won't be able to accept this instance. 193 * 194 * <p> 195 * This is very difficult to solve in general, but one seemingly 196 * easy solution is to use the type of next event. If a text is 197 * followed by a start tag, it follows from the constraint on 198 * RELAX NG that that text must be either whitespaces or a match 199 * to <text/>. 200 * 201 * <p> 202 * On the contrary, if a text is followed by a end tag, then it 203 * cannot be whitespace unless the content model can accept empty, 204 * in which case sending a text event will be harmlessly ignored 205 * by the NGCCHandler. 206 * 207 * <p> 208 * Thus this method take one parameter, which controls the 209 * behavior of this method. 466 ); 467 468 redirect.startElement(uri,local,qname,currentAtts); 469 redirectionDepth=1; 470 } 471 472 // 473 // 474 // validation context implementation 475 // 476 // 477 /** in-scope namespace mapping. 478 * namespaces[2n ] := prefix 479 * namespaces[2n+1] := namespace URI */ 480 private final ArrayList namespaces = new ArrayList(); 481 /** 482 * Index on the namespaces array, which points to 483 * the top of the effective bindings. Because of the 484 * timing difference between the startPrefixMapping method 485 * and the execution of the corresponding actions, 486 * this value can be different from {@code namespaces.size()}. 487 * <p> 488 * For example, consider the following schema: 489 * <pre>{@code 490 * <oneOrMore> 491 * <element name="foo"><empty/></element> 492 * </oneOrMore> 493 * code fragment X 494 * <element name="bob"/> 495 * }</pre> 496 * Code fragment X is executed after we see a startElement event, 497 * but at this time the namespaces variable already include new 498 * namespace bindings declared on "bob". 499 */ 500 private int nsEffectivePtr=0; 501 502 /** 503 * Stack to preserve old nsEffectivePtr values. 504 */ 505 private final Stack nsEffectiveStack = new Stack(); 506 507 public String resolveNamespacePrefix( String prefix ) { 508 for( int i = nsEffectivePtr-2; i>=0; i-=2 ) 509 if( namespaces.get(i).equals(prefix) ) 510 return (String)namespaces.get(i+1); 511 512 // no binding was found. 513 if(prefix.equals("")) return ""; // return the default no-namespace 514 if(prefix.equals("xml")) // pre-defined xml prefix 515 return "http://www.w3.org/XML/1998/namespace"; |