1 package net.sf.saxon.functions; 2 import net.sf.saxon.Controller; 3 import net.sf.saxon.Configuration; 4 import net.sf.saxon.event.Builder; 5 import net.sf.saxon.event.Receiver; 6 import net.sf.saxon.event.Sender; 7 import net.sf.saxon.event.PipelineConfiguration; 8 import net.sf.saxon.expr.*; 9 import net.sf.saxon.om.*; 10 import net.sf.saxon.sort.DocumentOrderIterator; 11 import net.sf.saxon.sort.GlobalOrderComparer; 12 import net.sf.saxon.trans.DynamicError; 13 import net.sf.saxon.trans.XPathException; 14 import net.sf.saxon.value.Cardinality; 15 16 import javax.xml.transform.Source ; 17 import javax.xml.transform.TransformerException ; 18 import javax.xml.transform.URIResolver ; 19 import javax.xml.transform.SourceLocator ; 20 import javax.xml.transform.dom.DOMSource ; 21 import java.net.URI ; 22 import java.net.URISyntaxException ; 23 24 25 28 29 public class Document extends SystemFunction implements XSLTFunction { 30 31 private String expressionBaseURI = null; 32 33 public void checkArguments(StaticContext env) throws XPathException { 34 if (expressionBaseURI == null) { 35 super.checkArguments(env); 38 expressionBaseURI = env.getBaseURI(); 39 Optimizer opt = env.getConfiguration().getOptimizer(); 40 argument[0] = ExpressionTool.unsorted(opt, argument[0], false); 41 } 42 } 43 44 47 48 public int computeCardinality() { 49 Expression expression = argument[0]; 50 if (Cardinality.allowsMany(expression.getCardinality())) { 51 return StaticProperty.ALLOWS_ZERO_OR_MORE; 52 } else { 53 return StaticProperty.ALLOWS_ZERO_OR_ONE; 54 } 55 } 57 58 63 64 public int computeSpecialProperties() { 65 return StaticProperty.ORDERED_NODESET | 66 StaticProperty.PEER_NODESET | 67 StaticProperty.NON_CREATIVE; 68 } 73 74 77 78 public Expression preEvaluate(StaticContext env) { 79 return this; 80 } 81 82 83 87 88 public SequenceIterator iterate(XPathContext context) throws XPathException { 89 int numArgs = argument.length; 90 91 SequenceIterator hrefSequence = argument[0].iterate(context); 92 String baseURI = null; 93 if (numArgs==2) { 94 NodeInfo base = (NodeInfo)argument[1].evaluateItem(context); 96 baseURI = base.getBaseURI(); 97 } 98 99 DocumentMappingFunction map = new DocumentMappingFunction(); 100 map.baseURI = baseURI; 101 map.stylesheetURI = expressionBaseURI; 102 map.locator = this; 103 104 MappingIterator iter = new MappingIterator(hrefSequence, map, context); 105 106 Expression expression = argument[0]; 107 if (Cardinality.allowsMany(expression.getCardinality())) { 108 return new DocumentOrderIterator(iter, GlobalOrderComparer.getInstance()); 109 } else { 111 return iter; 112 } 113 } 114 115 private static class DocumentMappingFunction implements MappingFunction { 116 117 public String baseURI; 118 public String stylesheetURI; 119 public SourceLocator locator; 120 121 124 125 public Object map(Item item, XPathContext context) throws XPathException { 126 127 if (baseURI==null) { 128 if (item instanceof NodeInfo) { 129 baseURI = ((NodeInfo)item).getBaseURI(); 130 } else { 131 baseURI = stylesheetURI; 132 } 133 } 134 NodeInfo doc = makeDoc(item.getStringValue(), baseURI, context, locator); 135 return doc; 136 } 137 } 138 139 140 143 144 public static NodeInfo makeDoc(String href, String baseURL, XPathContext c, SourceLocator locator) 145 throws XPathException { 146 147 149 int hash = href.indexOf('#'); 150 151 String fragmentId = null; 152 if (hash>=0) { 153 if (hash==href.length()-1) { 154 href = href.substring(0, hash); 156 } else { 157 fragmentId = href.substring(hash+1); 158 href = href.substring(0, hash); 159 } 160 } 161 162 163 165 String documentKey; 166 if (baseURL==null) { try { 168 documentKey = (new URI (href)).toString(); 170 } catch (URISyntaxException err) { 171 documentKey = '/' + href; 173 baseURL = ""; 174 } 175 } else if (href.equals("")) { 176 documentKey = baseURL; 178 } else { 179 try { 180 URI url = new URI (baseURL).resolve(href); 181 documentKey = url.toString(); 182 } catch (URISyntaxException err) { 183 documentKey = baseURL + "/../" + href; 184 } catch (IllegalArgumentException err) { 185 documentKey = baseURL + "/../" + href; 186 } 187 } 188 189 Controller controller = c.getController(); 190 191 193 194 DocumentInfo doc = controller.getDocumentPool().find(documentKey); 195 if (doc != null) { 196 return getFragment(doc, fragmentId, c); 197 } 198 199 try { 200 202 URIResolver r = controller.getURIResolver(); 203 Source source = null; 204 if (r != null) { 205 source = r.resolve(href, baseURL); 206 } 207 208 if (source==null) { 211 r = controller.getStandardURIResolver(); 212 source = r.resolve(href, baseURL); 213 } 214 215 Configuration config = controller.getConfiguration(); 216 source = config.getSourceResolver().resolveSource(source, config); 217 218 DocumentInfo newdoc; 219 if (source instanceof NodeInfo || source instanceof DOMSource ) { 220 NodeInfo startNode = controller.prepareInputTree(source); 221 newdoc = startNode.getDocumentRoot(); 222 } else { 223 Builder b = controller.makeBuilder(); 224 Receiver s = controller.makeStripper(b); 225 if (controller.getExecutable().stripsInputTypeAnnotations()) { 226 s = controller.getConfiguration().getAnnotationStripper(s); 227 } 228 new Sender(controller.makePipelineConfiguration()).send(source, s); 229 newdoc = (DocumentInfo)b.getCurrentRoot(); 230 } 231 controller.registerDocument(newdoc, documentKey); 232 return getFragment(newdoc, fragmentId, c); 233 234 } catch (TransformerException err) { 235 DynamicError xerr = DynamicError.makeDynamicError(err); 236 xerr.setLocator(locator); 237 xerr.setErrorCode("FODC0005"); 238 try { 239 controller.recoverableError(xerr); 240 } catch (XPathException err2) { 241 throw new DynamicError(err); 242 } 243 return null; 244 } 245 } 246 247 251 252 public void sendDocuments(XPathContext context, Receiver out) throws XPathException { 253 SequenceIterator hrefSequence = argument[0].iterate(context); 254 String explicitBaseURI = null; 255 if (argument.length==2) { 256 NodeInfo base = (NodeInfo)argument[1].evaluateItem(context); 258 explicitBaseURI = base.getBaseURI(); 259 } 260 while (true) { 261 Item href = hrefSequence.next(); 262 if (href == null) { 263 break; 264 } 265 String base; 266 if (explicitBaseURI == null) { 267 if (href instanceof NodeInfo) { 268 base = ((NodeInfo)href).getBaseURI(); 269 } else { 270 base = expressionBaseURI; 271 } 272 } else { 273 base = explicitBaseURI; 274 } 275 sendDoc(href.getStringValue(), base, context, this, out); 276 } 277 } 278 279 283 284 public static void sendDoc(String href, String baseURL, XPathContext c, SourceLocator locator, Receiver out) throws XPathException { 285 286 PipelineConfiguration pipe = out.getPipelineConfiguration(); 287 if (pipe == null) { 288 pipe = c.getController().makePipelineConfiguration(); 289 } 290 291 293 String documentKey; 294 if (baseURL==null) { try { 296 documentKey = (new URI (href)).toString(); 298 } catch (URISyntaxException err) { 299 documentKey = '/' + href; 301 baseURL = ""; 302 } 303 } else if (href.equals("")) { 304 documentKey = baseURL; 306 } else { 307 try { 308 URI url = new URI (baseURL).resolve(href); 309 documentKey = url.toString(); 310 } catch (URISyntaxException err) { 311 documentKey = baseURL + "/../" + href; 312 } catch (IllegalArgumentException err) { 313 documentKey = baseURL + "/../" + href; 314 } 315 } 316 317 Controller controller = c.getController(); 318 319 321 DocumentInfo doc = controller.getDocumentPool().find(documentKey); 322 Source source = null; 323 if (doc != null) { 324 source = doc; 325 } else { 326 327 try { 328 330 URIResolver r = controller.getURIResolver(); 331 if (r != null) { 332 source = r.resolve(href, baseURL); 333 } 334 335 if (source==null) { 338 r = controller.getStandardURIResolver(); 339 source = r.resolve(href, baseURL); 340 } 341 if (source instanceof NodeInfo || source instanceof DOMSource ) { 342 NodeInfo startNode = controller.prepareInputTree(source); 343 source = startNode.getDocumentRoot(); 344 } 345 } catch (TransformerException err) { 346 DynamicError xerr = DynamicError.makeDynamicError(err); 347 xerr.setLocator(locator); 348 xerr.setErrorCode("FODC0005"); 349 throw xerr; 350 } 351 } 352 out = controller.makeStripper(out); 353 out.setPipelineConfiguration(pipe); 354 if (controller.getExecutable().stripsInputTypeAnnotations()) { 355 out = controller.getConfiguration().getAnnotationStripper(out); 356 out.setPipelineConfiguration(pipe); 357 } 358 new Sender(pipe).send(source, out); 359 } 360 361 362 369 370 private static NodeInfo getFragment(DocumentInfo doc, String fragmentId, XPathContext context) 371 throws XPathException { 372 if (fragmentId==null) { 376 return doc; 377 } 378 if (!XMLChar.isValidNCName(fragmentId)) { 379 DynamicError err = new DynamicError("Invalid fragment identifier in URI"); 380 err.setXPathContext(context); 381 err.setErrorCode("XTRE1160"); 382 try { 383 context.getController().recoverableError(err); 384 } catch (DynamicError dynamicError) { 385 throw err; 386 } 387 return doc; 388 } 389 return doc.selectID(fragmentId); 390 } 391 392 393 } 394 395 396 397 398 399 | Popular Tags |