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