如何更改Java Transformer中的默认日志记录

jha*_*ley 6 java xml

我实现了代码,使我能够打印格式化的XML

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class TransformThis implements ErrorListener {

    public static void main(String[] args) throws java.lang.Exception {

        TransformThis test = new TransformThis();
        String goodXML;
        String badXML;

       goodXML = "<root><level1>WellFormed</level1></root>";
       System.out.println(test.prettyPrint(goodXML));
       badXML = "<root><level1>Not Well Formed</level1>";
       System.out.println(test.prettyPrint(badXML));
   }

   public String prettyPrint(String xml) {

       Source xmlInput = new StreamSource(new StringReader(xml));
       StringWriter stringWriter = new StringWriter();
       StreamResult xmlOutput = new StreamResult(stringWriter);
       TransformerFactory transformerFactory = TransformerFactory.newInstance();
       transformerFactory.setAttribute("indent-number", 4);

       try {
           Transformer transformer = transformerFactory.newTransformer();
           transformer.setErrorListener(this);
           transformer.setOutputProperty(OutputKeys.INDENT, "yes");
           transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
           transformer.transform(xmlInput, xmlOutput);
       } catch (Exception ex) {
           System.out.println("My message: " + ex.getMessage());
       }

       return xmlOutput.getWriter().toString();
   }


   @Override
   public void warning(TransformerException exception) throws TransformerException {
       //throw new UnsupportedOperationException("Not supported yet.");
   }

   @Override
   public void error(TransformerException exception) throws TransformerException {
      //throw new UnsupportedOperationException("Not supported yet.");
   }

   @Override
   public void fatalError(TransformerException exception) throws TransformerException {
       //throw new UnsupportedOperationException("Not supported yet.");
   }
}
Run Code Online (Sandbox Code Playgroud)

当XML格式正确时,我得到以下输出 - 正是我想要的

<root>
    <level1>WellFormed</level1>
</root>
Run Code Online (Sandbox Code Playgroud)

如果XML存在问题,我会得到以下输出 - 很好,除了[致命错误]输出

[Fatal Error] :1:39: XML document structures must start and end within the same entity.
My message: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 39; XML document structures must start and end within the same entity.
<root>
   <level1>Not Well Formed</level1>
Run Code Online (Sandbox Code Playgroud)

transform函数抛出异常并向stderr/stdout发送[Fatal Error].有没有办法防止出现[致命错误]日志?

Bri*_*ach 6

您在JDK中发现了一个错误(实际上是两个).恭喜!(或者,我想,哀悼).

第一个错误是它是一个"致命"错误,但它会调用ErrorListener.error()而不是ErrorListener.fatalError().如果你在你的例子中加入一个println语句error(),你会看到它被调用.

第二个错误是忽略了上面的第一个错误,你正在做的事情应该有效.

但事实并非如此.

在调试器中抛出您的示例并深入研究JDK我发现错误监听器没有传播到底层XMLScannerXMLErrorReporter.

发生的事情是,XMLErrorReporter实例化a com.sun.org.apache.xerces.internal.util.DefaultErrorHandler并调用它的fatalError()方法,这就是将[fatal error]消息吐出的内容stderr.

具体而言,这发生在第422行com.sun.org.apache.xerces.internal.impl.XMLErrorReporter

之后,它会将异常重新抛出堆栈并将其TransformerImpl激发给您的侦听器.

应该发生的是,那些底层类应该具有您传入的更高级别侦听器的代理,或者应该创建本地无操作侦听器以使较低级别的输出静音.我怀疑它是后者,否则你会得到两次通知.

我需要更仔细地查看抽象树并调试构造链以找出为什么没有发生但简而言之,遗憾的是这是JDK中的一个错误,并且没有办法控制/阻止它.(这是在Java 1.7.0_25-b15上测试的).


Jon*_*les 5

根据布莱恩·罗奇的回答......有一种替代方法可以解决这个问题。如果您使用 aStreamSource作为变压器的输入,那么您将不得不使用系统决定提供给您的任何解析器以及解析器选择的默认错误报告机制。不过,您可以使用 SAX 或 DOM 源,它允许您自己配置解析器。我已更新您的示例以使用SAXSource实例。

public class TransformThis implements ErrorListener, ErrorHandler {

    public static void main(String[] args) throws java.lang.Exception {

        TransformThis test = new TransformThis();
        String goodXML;
        String badXML;

       goodXML = "<root><level1>WellFormed</level1></root>";
       System.out.println(test.prettyPrint(goodXML));
       badXML = "<root><level1>Not Well Formed</level1>";
       System.out.println(test.prettyPrint(badXML));
   }

   public String prettyPrint(String xml) throws ParserConfigurationException, SAXException {

       SAXParserFactory parserFactory = SAXParserFactory.newInstance();
       SAXParser parser = parserFactory.newSAXParser();
       parser.getXMLReader().setErrorHandler(this);       
       SAXSource xmlInput = new SAXSource(parser.getXMLReader(), new InputSource(new StringReader(xml)));

       StringWriter stringWriter = new StringWriter();
       StreamResult xmlOutput = new StreamResult(stringWriter);
       TransformerFactory transformerFactory = TransformerFactory.newInstance();
       transformerFactory.setAttribute("indent-number", 4);

       try {
           Transformer transformer = transformerFactory.newTransformer();
           transformer.setErrorListener(this);
           transformer.setOutputProperty(OutputKeys.INDENT, "yes");
           transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
           transformer.transform(xmlInput, xmlOutput);
       } catch (Exception ex) {
           System.out.println("My message: " + ex.getMessage());
       }

       return xmlOutput.getWriter().toString();
   }


   @Override
   public void warning(TransformerException exception) throws TransformerException {
       //throw new UnsupportedOperationException("Not supported yet.");
   }

   @Override
   public void error(TransformerException exception) throws TransformerException {
      //throw new UnsupportedOperationException("Not supported yet.");
   }

   @Override
   public void fatalError(TransformerException exception) throws TransformerException {
       //throw new UnsupportedOperationException("Not supported yet.");
   }

   @Override
   public void warning(SAXParseException exception) throws SAXException {
       // Do nothing
   }

   @Override
   public void error(SAXParseException exception) throws SAXException {
       // Do nothing
   }

   @Override
   public void fatalError(SAXParseException exception) throws SAXException {
       // Rethrow the exception
       throw exception;
   }

}
Run Code Online (Sandbox Code Playgroud)