1 /*
2 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements. See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 /*
21 * $Id: TransformerImpl.java,v 1.10 2007/06/13 01:57:09 joehw Exp $
22 */
43 import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
44 import com.sun.org.apache.xml.internal.utils.XMLReaderManager;
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.OutputStream;
50 import java.io.Reader;
51 import java.io.Writer;
52 import java.net.URI;
53 import java.net.URL;
54 import java.net.URLConnection;
55 import java.net.UnknownServiceException;
56 import java.util.ArrayList;
57 import java.util.Enumeration;
58 import java.util.HashMap;
59 import java.util.Map;
60 import java.util.Properties;
61 import java.util.StringTokenizer;
62 import javax.xml.XMLConstants;
63 import javax.xml.parsers.DocumentBuilder;
64 import javax.xml.parsers.DocumentBuilderFactory;
65 import javax.xml.parsers.ParserConfigurationException;
66 import javax.xml.stream.XMLEventReader;
67 import javax.xml.stream.XMLStreamReader;
68 import javax.xml.transform.ErrorListener;
69 import javax.xml.transform.OutputKeys;
70 import javax.xml.transform.Result;
71 import javax.xml.transform.Source;
72 import javax.xml.transform.Transformer;
73 import javax.xml.transform.TransformerException;
74 import javax.xml.transform.URIResolver;
75 import javax.xml.transform.dom.DOMResult;
76 import javax.xml.transform.dom.DOMSource;
77 import javax.xml.transform.sax.SAXResult;
78 import javax.xml.transform.sax.SAXSource;
79 import javax.xml.transform.stax.StAXResult;
80 import javax.xml.transform.stax.StAXSource;
81 import javax.xml.transform.stream.StreamResult;
82 import javax.xml.transform.stream.StreamSource;
83 import org.xml.sax.ContentHandler;
84 import org.xml.sax.InputSource;
85 import org.xml.sax.SAXException;
86 import org.xml.sax.XMLReader;
87 import org.xml.sax.ext.LexicalHandler;
88
89 /**
90 * @author Morten Jorgensen
91 * @author G. Todd Miller
92 * @author Santiago Pericas-Geertsen
93 */
94 public final class TransformerImpl extends Transformer
95 implements DOMCache, ErrorListener
96 {
97
98 private final static String LEXICAL_HANDLER_PROPERTY =
99 "http://xml.org/sax/properties/lexical-handler";
100 private static final String NAMESPACE_FEATURE =
101 "http://xml.org/sax/features/namespaces";
102
200 * Note the default value (false) is the safe option..
201 */
202 private boolean _useServicesMechanism;
203 /**
204 * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
205 */
206 private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
207 /**
208 * protocols allowed for external DTD references in source file and/or stylesheet.
209 */
210 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
211
212 private XMLSecurityManager _securityManager;
213 /**
214 * A map to store parameters for the identity transform. These
215 * are not needed during the transformation, but we must keep track of
216 * them to be fully complaint with the JAXP API.
217 */
218 private Map<String, Object> _parameters = null;
219
220 /**
221 * This class wraps an ErrorListener into a MessageHandler in order to
222 * capture messages reported via xsl:message.
223 */
224 static class MessageHandler
225 extends com.sun.org.apache.xalan.internal.xsltc.runtime.MessageHandler
226 {
227 private ErrorListener _errorListener;
228
229 public MessageHandler(ErrorListener errorListener) {
230 _errorListener = errorListener;
231 }
232
233 @Override
234 public void displayMessage(String msg) {
235 if(_errorListener == null) {
236 System.err.println(msg);
237 }
238 else {
239 try {
253 _isIdentity = true;
254 // _properties.put(OutputKeys.METHOD, "xml");
255 }
256
257 protected TransformerImpl(Translet translet, Properties outputProperties,
258 int indentNumber, TransformerFactoryImpl tfactory)
259 {
260 _translet = (AbstractTranslet) translet;
261 _properties = createOutputProperties(outputProperties);
262 _propertiesClone = (Properties) _properties.clone();
263 _indentNumber = indentNumber;
264 _tfactory = tfactory;
265 _useServicesMechanism = _tfactory.useServicesMechnism();
266 _accessExternalStylesheet = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
267 _accessExternalDTD = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
268 _securityManager = (XMLSecurityManager)_tfactory.getAttribute(XalanConstants.SECURITY_MANAGER);
269 _readerManager = XMLReaderManager.getInstance(_useServicesMechanism);
270 _readerManager.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
271 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing);
272 _readerManager.setProperty(XalanConstants.SECURITY_MANAGER, _securityManager);
273 //_isIncremental = tfactory._incremental;
274 }
275
276 /**
277 * Return the state of the secure processing feature.
278 */
279 public boolean isSecureProcessing() {
280 return _isSecureProcessing;
281 }
282
283 /**
284 * Set the state of the secure processing feature.
285 */
286 public void setSecureProcessing(boolean flag) {
287 _isSecureProcessing = flag;
288 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing);
289 }
290 /**
291 * Return the state of the services mechanism feature.
292 */
322 */
323 @Override
324 public void transform(Source source, Result result)
325 throws TransformerException
326 {
327 if (!_isIdentity) {
328 if (_translet == null) {
329 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
330 throw new TransformerException(err.toString());
331 }
332 // Pass output properties to the translet
333 transferOutputProperties(_translet);
334 }
335
336 final SerializationHandler toHandler = getOutputHandler(result);
337 if (toHandler == null) {
338 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
339 throw new TransformerException(err.toString());
340 }
341
342 if (_uriResolver != null && !_isIdentity) {
343 _translet.setDOMCache(this);
344 }
345
346 // Pass output properties to handler if identity
347 if (_isIdentity) {
348 transferOutputProperties(toHandler);
349 }
350
351 transform(source, toHandler, _encoding);
352 try{
353 if (result instanceof DOMResult) {
354 ((DOMResult)result).setNode(_tohFactory.getNode());
355 } else if (result instanceof StAXResult) {
356 if (((StAXResult) result).getXMLEventWriter() != null)
357 {
358 (_tohFactory.getXMLEventWriter()).flush();
359 }
360 else if (((StAXResult) result).getXMLStreamWriter() != null) {
361 (_tohFactory.getXMLStreamWriter()).flush();
362 //result = new StAXResult(_tohFactory.getXMLStreamWriter());
706 private void transform(Source source, SerializationHandler handler,
707 String encoding) throws TransformerException
708 {
709 try {
710 /*
711 * According to JAXP1.2, new SAXSource()/StreamSource()
712 * should create an empty input tree, with a default root node.
713 * new DOMSource()creates an empty document using DocumentBuilder.
714 * newDocument(); Use DocumentBuilder.newDocument() for all 3
715 * situations, since there is no clear spec. how to create
716 * an empty tree when both SAXSource() and StreamSource() are used.
717 */
718 if ((source instanceof StreamSource && source.getSystemId()==null
719 && ((StreamSource)source).getInputStream()==null &&
720 ((StreamSource)source).getReader()==null)||
721 (source instanceof SAXSource &&
722 ((SAXSource)source).getInputSource()==null &&
723 ((SAXSource)source).getXMLReader()==null )||
724 (source instanceof DOMSource &&
725 ((DOMSource)source).getNode()==null)){
726 DocumentBuilderFactory builderF = FactoryImpl.getDOMFactory(_useServicesMechanism);
727 DocumentBuilder builder = builderF.newDocumentBuilder();
728 String systemID = source.getSystemId();
729 source = new DOMSource(builder.newDocument());
730
731 // Copy system ID from original, empty Source to new
732 if (systemID != null) {
733 source.setSystemId(systemID);
734 }
735 }
736 if (_isIdentity) {
737 transformIdentity(source, handler);
738 } else {
739 _translet.transform(getDOM(source), handler);
740 }
741 } catch (TransletException e) {
742 if (_errorListener != null) postErrorToListener(e.getMessage());
743 throw new TransformerException(e);
744 } catch (RuntimeException e) {
745 if (_errorListener != null) postErrorToListener(e.getMessage());
746 throw new TransformerException(e);
1270 * @param baseURI The base URI used by the document call.
1271 * @param href The href argument passed to the document function.
1272 * @param translet A reference to the translet requesting the document
1273 */
1274 @Override
1275 public DOM retrieveDocument(String baseURI, String href, Translet translet) {
1276 try {
1277 // Argument to document function was: document('');
1278 if (href.length() == 0) {
1279 href = baseURI;
1280 }
1281
1282 /*
1283 * Fix for bug 24188
1284 * Incase the _uriResolver.resolve(href,base) is null
1285 * try to still retrieve the document before returning null
1286 * and throwing the FileNotFoundException in
1287 * com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument
1288 *
1289 */
1290 Source resolvedSource = _uriResolver.resolve(href, baseURI);
1291 if (resolvedSource == null) {
1292 StreamSource streamSource = new StreamSource(
1293 SystemIDResolver.getAbsoluteURI(href, baseURI));
1294 return getDOM(streamSource) ;
1295 }
1296
1297 return getDOM(resolvedSource);
1298 }
1299 catch (TransformerException e) {
1300 if (_errorListener != null)
1301 postErrorToListener("File not found: " + e.getMessage());
1302 return(null);
1303 }
1304 }
1305
1306 /**
1307 * Receive notification of a recoverable error.
1308 * The transformer must continue to provide normal parsing events after
1309 * invoking this method. It should still be possible for the application
1310 * to process the document through to the end.
|
1 /*
2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements. See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 /*
21 * $Id: TransformerImpl.java,v 1.10 2007/06/13 01:57:09 joehw Exp $
22 */
43 import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
44 import com.sun.org.apache.xml.internal.utils.XMLReaderManager;
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.OutputStream;
50 import java.io.Reader;
51 import java.io.Writer;
52 import java.net.URI;
53 import java.net.URL;
54 import java.net.URLConnection;
55 import java.net.UnknownServiceException;
56 import java.util.ArrayList;
57 import java.util.Enumeration;
58 import java.util.HashMap;
59 import java.util.Map;
60 import java.util.Properties;
61 import java.util.StringTokenizer;
62 import javax.xml.XMLConstants;
63 import javax.xml.catalog.CatalogFeatures;
64 import javax.xml.catalog.CatalogManager;
65 import javax.xml.catalog.CatalogUriResolver;
66 import javax.xml.parsers.DocumentBuilder;
67 import javax.xml.parsers.DocumentBuilderFactory;
68 import javax.xml.parsers.ParserConfigurationException;
69 import javax.xml.stream.XMLEventReader;
70 import javax.xml.stream.XMLStreamReader;
71 import javax.xml.transform.ErrorListener;
72 import javax.xml.transform.OutputKeys;
73 import javax.xml.transform.Result;
74 import javax.xml.transform.Source;
75 import javax.xml.transform.Transformer;
76 import javax.xml.transform.TransformerException;
77 import javax.xml.transform.URIResolver;
78 import javax.xml.transform.dom.DOMResult;
79 import javax.xml.transform.dom.DOMSource;
80 import javax.xml.transform.sax.SAXResult;
81 import javax.xml.transform.sax.SAXSource;
82 import javax.xml.transform.stax.StAXResult;
83 import javax.xml.transform.stax.StAXSource;
84 import javax.xml.transform.stream.StreamResult;
85 import javax.xml.transform.stream.StreamSource;
86 import jdk.xml.internal.JdkXmlFeatures;
87 import jdk.xml.internal.JdkXmlUtils;
88 import org.xml.sax.ContentHandler;
89 import org.xml.sax.InputSource;
90 import org.xml.sax.SAXException;
91 import org.xml.sax.XMLReader;
92 import org.xml.sax.ext.LexicalHandler;
93
94 /**
95 * @author Morten Jorgensen
96 * @author G. Todd Miller
97 * @author Santiago Pericas-Geertsen
98 */
99 public final class TransformerImpl extends Transformer
100 implements DOMCache, ErrorListener
101 {
102
103 private final static String LEXICAL_HANDLER_PROPERTY =
104 "http://xml.org/sax/properties/lexical-handler";
105 private static final String NAMESPACE_FEATURE =
106 "http://xml.org/sax/features/namespaces";
107
205 * Note the default value (false) is the safe option..
206 */
207 private boolean _useServicesMechanism;
208 /**
209 * protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
210 */
211 private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
212 /**
213 * protocols allowed for external DTD references in source file and/or stylesheet.
214 */
215 private String _accessExternalDTD = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
216
217 private XMLSecurityManager _securityManager;
218 /**
219 * A map to store parameters for the identity transform. These
220 * are not needed during the transformation, but we must keep track of
221 * them to be fully complaint with the JAXP API.
222 */
223 private Map<String, Object> _parameters = null;
224
225 // Catalog features
226 CatalogFeatures _catalogFeatures;
227 CatalogUriResolver _catalogUriResolver;
228
229 // Catalog is enabled by default
230 boolean _useCatalog = true;
231
232
233 /**
234 * This class wraps an ErrorListener into a MessageHandler in order to
235 * capture messages reported via xsl:message.
236 */
237 static class MessageHandler
238 extends com.sun.org.apache.xalan.internal.xsltc.runtime.MessageHandler
239 {
240 private ErrorListener _errorListener;
241
242 public MessageHandler(ErrorListener errorListener) {
243 _errorListener = errorListener;
244 }
245
246 @Override
247 public void displayMessage(String msg) {
248 if(_errorListener == null) {
249 System.err.println(msg);
250 }
251 else {
252 try {
266 _isIdentity = true;
267 // _properties.put(OutputKeys.METHOD, "xml");
268 }
269
270 protected TransformerImpl(Translet translet, Properties outputProperties,
271 int indentNumber, TransformerFactoryImpl tfactory)
272 {
273 _translet = (AbstractTranslet) translet;
274 _properties = createOutputProperties(outputProperties);
275 _propertiesClone = (Properties) _properties.clone();
276 _indentNumber = indentNumber;
277 _tfactory = tfactory;
278 _useServicesMechanism = _tfactory.useServicesMechnism();
279 _accessExternalStylesheet = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET);
280 _accessExternalDTD = (String)_tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD);
281 _securityManager = (XMLSecurityManager)_tfactory.getAttribute(XalanConstants.SECURITY_MANAGER);
282 _readerManager = XMLReaderManager.getInstance(_useServicesMechanism);
283 _readerManager.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
284 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing);
285 _readerManager.setProperty(XalanConstants.SECURITY_MANAGER, _securityManager);
286
287 _useCatalog = _tfactory.getFeature(XMLConstants.USE_CATALOG);
288 if (_useCatalog) {
289 _catalogFeatures = (CatalogFeatures)_tfactory.getAttribute(JdkXmlFeatures.CATALOG_FEATURES);
290 String catalogFiles = _catalogFeatures.get(CatalogFeatures.Feature.DEFER);
291 if (catalogFiles != null) {
292 _readerManager.setFeature(XMLConstants.USE_CATALOG, _useCatalog);
293 _readerManager.setProperty(JdkXmlFeatures.CATALOG_FEATURES, _catalogFeatures);
294 }
295 }
296 //_isIncremental = tfactory._incremental;
297 }
298
299 /**
300 * Return the state of the secure processing feature.
301 */
302 public boolean isSecureProcessing() {
303 return _isSecureProcessing;
304 }
305
306 /**
307 * Set the state of the secure processing feature.
308 */
309 public void setSecureProcessing(boolean flag) {
310 _isSecureProcessing = flag;
311 _readerManager.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, _isSecureProcessing);
312 }
313 /**
314 * Return the state of the services mechanism feature.
315 */
345 */
346 @Override
347 public void transform(Source source, Result result)
348 throws TransformerException
349 {
350 if (!_isIdentity) {
351 if (_translet == null) {
352 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_TRANSLET_ERR);
353 throw new TransformerException(err.toString());
354 }
355 // Pass output properties to the translet
356 transferOutputProperties(_translet);
357 }
358
359 final SerializationHandler toHandler = getOutputHandler(result);
360 if (toHandler == null) {
361 ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_NO_HANDLER_ERR);
362 throw new TransformerException(err.toString());
363 }
364
365 if (!_isIdentity && (_uriResolver != null || (_tfactory.getFeature(XMLConstants.USE_CATALOG)
366 && _tfactory.getAttribute(JdkXmlUtils.CATALOG_FILES) != null))) {
367 _translet.setDOMCache(this);
368 }
369
370 // Pass output properties to handler if identity
371 if (_isIdentity) {
372 transferOutputProperties(toHandler);
373 }
374
375 transform(source, toHandler, _encoding);
376 try{
377 if (result instanceof DOMResult) {
378 ((DOMResult)result).setNode(_tohFactory.getNode());
379 } else if (result instanceof StAXResult) {
380 if (((StAXResult) result).getXMLEventWriter() != null)
381 {
382 (_tohFactory.getXMLEventWriter()).flush();
383 }
384 else if (((StAXResult) result).getXMLStreamWriter() != null) {
385 (_tohFactory.getXMLStreamWriter()).flush();
386 //result = new StAXResult(_tohFactory.getXMLStreamWriter());
730 private void transform(Source source, SerializationHandler handler,
731 String encoding) throws TransformerException
732 {
733 try {
734 /*
735 * According to JAXP1.2, new SAXSource()/StreamSource()
736 * should create an empty input tree, with a default root node.
737 * new DOMSource()creates an empty document using DocumentBuilder.
738 * newDocument(); Use DocumentBuilder.newDocument() for all 3
739 * situations, since there is no clear spec. how to create
740 * an empty tree when both SAXSource() and StreamSource() are used.
741 */
742 if ((source instanceof StreamSource && source.getSystemId()==null
743 && ((StreamSource)source).getInputStream()==null &&
744 ((StreamSource)source).getReader()==null)||
745 (source instanceof SAXSource &&
746 ((SAXSource)source).getInputSource()==null &&
747 ((SAXSource)source).getXMLReader()==null )||
748 (source instanceof DOMSource &&
749 ((DOMSource)source).getNode()==null)){
750
751 boolean supportCatalog = true;
752
753 DocumentBuilderFactory builderF = FactoryImpl.getDOMFactory(_useServicesMechanism);
754 try {
755 builderF.setFeature(XMLConstants.USE_CATALOG, _useCatalog);
756 } catch (ParserConfigurationException e) {
757 supportCatalog = false;
758 }
759
760 if (supportCatalog && _useCatalog) {
761 CatalogFeatures cf = (CatalogFeatures)_tfactory.getAttribute(JdkXmlFeatures.CATALOG_FEATURES);
762 if (cf != null) {
763 for (CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
764 builderF.setAttribute(f.getPropertyName(), cf.get(f));
765 }
766 }
767 }
768
769 DocumentBuilder builder = builderF.newDocumentBuilder();
770 String systemID = source.getSystemId();
771 source = new DOMSource(builder.newDocument());
772
773 // Copy system ID from original, empty Source to new
774 if (systemID != null) {
775 source.setSystemId(systemID);
776 }
777 }
778 if (_isIdentity) {
779 transformIdentity(source, handler);
780 } else {
781 _translet.transform(getDOM(source), handler);
782 }
783 } catch (TransletException e) {
784 if (_errorListener != null) postErrorToListener(e.getMessage());
785 throw new TransformerException(e);
786 } catch (RuntimeException e) {
787 if (_errorListener != null) postErrorToListener(e.getMessage());
788 throw new TransformerException(e);
1312 * @param baseURI The base URI used by the document call.
1313 * @param href The href argument passed to the document function.
1314 * @param translet A reference to the translet requesting the document
1315 */
1316 @Override
1317 public DOM retrieveDocument(String baseURI, String href, Translet translet) {
1318 try {
1319 // Argument to document function was: document('');
1320 if (href.length() == 0) {
1321 href = baseURI;
1322 }
1323
1324 /*
1325 * Fix for bug 24188
1326 * Incase the _uriResolver.resolve(href,base) is null
1327 * try to still retrieve the document before returning null
1328 * and throwing the FileNotFoundException in
1329 * com.sun.org.apache.xalan.internal.xsltc.dom.LoadDocument
1330 *
1331 */
1332 Source resolvedSource = null;
1333 if (_uriResolver != null) {
1334 resolvedSource = _uriResolver.resolve(href, baseURI);
1335 }
1336
1337 if (resolvedSource == null && _useCatalog &&
1338 _catalogFeatures.get(CatalogFeatures.Feature.FILES) != null) {
1339 if (_catalogUriResolver == null) {
1340 _catalogUriResolver = CatalogManager.catalogUriResolver(_catalogFeatures);
1341 }
1342 resolvedSource = _catalogUriResolver.resolve(href, baseURI);
1343 }
1344
1345 if (resolvedSource == null) {
1346 StreamSource streamSource = new StreamSource(
1347 SystemIDResolver.getAbsoluteURI(href, baseURI));
1348 return getDOM(streamSource) ;
1349 }
1350
1351 return getDOM(resolvedSource);
1352 }
1353 catch (TransformerException e) {
1354 if (_errorListener != null)
1355 postErrorToListener("File not found: " + e.getMessage());
1356 return(null);
1357 }
1358 }
1359
1360 /**
1361 * Receive notification of a recoverable error.
1362 * The transformer must continue to provide normal parsing events after
1363 * invoking this method. It should still be possible for the application
1364 * to process the document through to the end.
|