简体   繁体   中英

How to handle XML-related exceptions in Java?

I'm working on an appliation that needs to read, manipulate and write XML documents. While working with the XML API, I had to catch several exceptions, and I'm not sure how to handle them.

Consider the following code:

public static void removeWhitespace(Document document)
{
    XPath xPath = getXPath();
    NodeList emptyTextNodes;
    try
    {
        XPathExpression expression = xPath.compile("//text()[normalize-space(.) = '']");
        emptyTextNodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
    }
    catch (XPathExpressionException e)
    {
        // How to handle this?
        return;
    }

    int nEmptyTextNodes = emptyTextNodes.getLength();
    for (int i = 0; i < nEmptyTextNodes; ++i)
    {
        Node node = emptyTextNodes.item(i);
        node.getParentNode().removeChild(node);
    }
}

The documentation for XPath#compile says that XPathExpressionException will be thrown "If expression cannot be compiled". However, in this case, the expression is hardcoded and (presumably) valid, so this shouldn't happen. Since this is a checked exception, I have to handle it - but what should I do in the catch block?

Similarly, the documentation for XPathExpression#evaluate says that XPathExpressionException will be thrown "If the expression cannot be evaluated". Since I believe the expression is valid, the only way I think this could happen is if the caller passes an invalid Document . How should I handle that?

Consider this method:

public static String documentToString(Document document)
{
    StringWriter writer = new StringWriter();
    try
    {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        transformer.transform(new DOMSource(document), new StreamResult(writer));
    }
    catch (TransformerException e)
    {
        // What happens now?
        return null;
    }

    String xml = writer.getBuffer().toString();
    // No need to close the StringWriter
    return xml;
}

TransformerFactory#newTransformer will throw a TransformerConfigurationException (would have linked the docs but SO won't let me) "When it is not possible to create a Transformer instance". How can this ever happen? How do I deal with it?

I could declare these exceptions to be thrown, but that would just move the problem somewhere else.

Under which circumstance will these exceptions be thrown, and how should I handle them?

Under which circumstance will these exceptions be thrown

These are possible causes for XML / XPath / XSLT related exceptions in the javax.xml packages:

  • invalid arguments passed to API methods
  • use of configurations which are optional and not supported by implementations
  • IO and encoding errors when reading a Source or writing a Result
  • Syntax errors when parsing a XML document, a XSLT stylesheet, a XPath expression
  • errors caused by executing an invalid operation (eg in XPath: calling a node-set function on a string or a number)
  • any other runtime error, most likely caused by a bug in the implementation

how should I handle them?

Like you treat all exceptions:

If can handle an exception, ie fix its cause or take some other action, then catch it and run the exception handler code in the catch block.

If you can't handle an exception let the caller handle it. For checked exceptions the simplest way is just to declare it in your methods throw clause. You could also catch an exception to convert it to another type (another checked exception, a RuntimeException or even an Error). Converting to a RuntimeException (eg a IllegalStateException) can be used if you don't want to have a checked exception in the method signature.

To your examples:

There is probably no possibility that your methods will fail (No disk IO operations, no syntax errors, all arguments ok, etc.). Still you can't handle the exception so you need to pass it to the caller. In the case of the two methods it could be irritating (but still justifiable) if the methods would declare XPathExpressionException and TransformerException . If you ask me I would catch the XPathExpressionException and TransformerException and rethrow them wrapped into a IllegalStateException .

This shouldn't happen [but], I have to handle it[, so] what should I do in the catch block?

If you really believe that it can not happen, If you are counting on it not to happen, and it turns out that you were wrong and the exception actually does happen, then that means your program is defective.

Here's the simplest handler for an exception that means the program is defective:

catch (TheException ex) {
    assert false;
}

Here's a better one:

import org.apache.log4j.Logger;
 ...
static final Logger LOGGER = ...;
 ...
catch (TheException ex) {
    LOGGER.fatal("Unexpected exception", ex);
    myApplication.makeSafeToShutdown(...);
    System.exit(1);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM