【问题标题】:How to handle XML-related exceptions in Java?如何在 Java 中处理与 XML 相关的异常?
【发布时间】:2023-03-23 13:25:01
【问题描述】:

我正在开发一个需要读取、操作和编写 XML 文档的应用程序。在使用 XML API 时,我必须捕获几个异常,但我不知道如何处理它们。

考虑以下代码:

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 表示XPathExpressionException 将被抛出“如果无法编译表达式”。但是,在这种情况下,表达式是硬编码的并且(可能)有效,因此不应该发生这种情况。由于这是一个检查异常,我必须处理它 - 但是我应该在 catch 块中做什么?

同样,the documentation for XPathExpression#evaluate 表示 XPathExpressionException 将被抛出“如果无法计算表达式”。因为我相信这个表达式是有效的,所以我认为这可能发生的唯一方法是调用者传递一个无效的Document。我该如何处理?

考虑这种方法:

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 将抛出 TransformerConfigurationException (将链接文档但 SO 不会让我)“当无法创建 Transformer 实例时”。这怎么可能发生?我该如何处理?

我可以声明要抛出这些异常,但这只会将问题转移到其他地方。

在什么情况下会抛出这些异常,应该如何处理?

【问题讨论】:

    标签: java xml xpath


    【解决方案1】:

    在什么情况下会抛出这些异常

    这些是javax.xml 包中与 XML / XPath / XSLT 相关的异常的可能原因:

    • 传递给 API 方法的参数无效
    • 使用可选配置,实施不支持
    • 读取 Source 或写入 Result 时出现 IO 和编码错误
    • 解析 XML 文档、XSLT 样式表、XPath 表达式时出现语法错误
    • 执行无效操作导致的错误(例如,在 XPath 中:对字符串或数字调用节点集函数)
    • 任何其他运行时错误,很可能是由实现中的错误引起的

    我应该如何处理它们?

    就像你对待所有例外一样:

    如果可以处理异常,即修复其原因或采取其他措施,则捕获它并在 catch 块中运行异常处理程序代码。

    如果您无法处理异常,请让调用者处理它。对于已检查的异常,最简单的方法就是在您的方法 throw 子句中声明它。 您还可以捕获异常以将其转换为另一种类型(另一个检查的异常、RuntimeException 甚至是错误)。如果您不想在方法签名中包含已检查的异常,则可以使用转换为 RuntimeException(例如 IllegalStateException)。

    举个例子:

    您的方法可能不会失败(无磁盘 IO 操作、无语法错误、所有参数正常等)。 您仍然无法处理异常,因此您需要将其传递给调用者。 在这两种方法的情况下,如果方法声明XPathExpressionExceptionTransformerException,可能会令人恼火(但仍然是合理的)。 如果你问我,我会抓住 XPathExpressionExceptionTransformerException 并将它们重新扔到 IllegalStateException 中。

    【讨论】:

      【解决方案2】:

      这不应该发生[但是],我必须处理它[,所以]我应该在 catch 块中做什么?

      如果你真的相信它不会发生,如果你指望它不会发生,而事实证明你错了,异常实际上确实发生了,那么这意味着你的程序有缺陷。

      这是表示程序有缺陷的异常的最简单处理程序:

      catch (TheException ex) {
          assert false;
      }
      

      这里有一个更好的:

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

      【讨论】:

      • 你也可以抛出一个错误(不可恢复的失败),这将允许调用者方法的任何 finally 块被执行。
      • @Javier,好点子。我只考虑程序的顶层,但你是对的:特别是在一个大系统中,更深层次的非顶层处理程序应该重新抛出他们无法处理的任何东西,让中间处理程序也有机会,直到它达到了最高水平。只有顶级处理程序应该退出程序。
      猜你喜欢
      • 2020-12-30
      • 1970-01-01
      • 2023-03-29
      • 2015-11-04
      • 2013-11-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多