[英]How do I change the default logging in Java Transformer
我實現了代碼 ,使我能夠打印格式化的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.");
}
}
當XML格式正確時,我得到以下輸出 - 正是我想要的
<root>
<level1>WellFormed</level1>
</root>
如果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>
transform函數拋出異常並向stderr / stdout發送[Fatal Error]。 有沒有辦法防止出現[致命錯誤]日志?
您在JDK中發現了一個錯誤(實際上是兩個)。 恭喜! (或者,我想,哀悼)。
第一個錯誤是它是一個“致命”錯誤,但它將調用ErrorListener.error()
而不是ErrorListener.fatalError()
。 如果在示例中將println
語句放在error()
中,您將看到它被調用。
第二個錯誤是忽略了上面的第一個錯誤,你正在做的事情應該有效。
但事實並非如此。
在調試器中拋出您的示例並深入研究JDK我發現錯誤偵聽器沒有傳播到底層的XMLScanner
和XMLErrorReporter
。
發生的事情是XMLErrorReporter
正在實例化一個com.sun.org.apache.xerces.internal.util.DefaultErrorHandler
並調用它的fatalError()
方法,這就是將[fatal error]
消息吐出到stderr
。
具體來說,這發生在com.sun.org.apache.xerces.internal.impl.XMLErrorReporter
第422行。
之后,它會將異常重新拋出堆棧, TransformerImpl
會將其激發給您的偵聽器。
應該發生的是,那些底層類應該具有您傳入的更高級別偵聽器的代理,或者應該創建本地無操作偵聽器以使較低級別的輸出靜音。 我懷疑它是后者,否則你會得到兩次通知。
我需要更仔細地查看抽象樹並調試構造鏈以找出為什么沒有發生但簡而言之,遺憾的是這是JDK中的一個錯誤,並且沒有辦法控制/阻止它。 (這是在Java 1.7.0_25-b15上測試的)。
繼Brian Brian的回答之后......還有另一種方法可以解決問題。 如果您使用StreamSource
作為變換器的輸入,那么您將無法使用系統決定為您提供的任何解析器,以及解析器選擇的默認錯誤報告機制。 但是,您可以使用SAX或DOM Source,它允許您自己配置解析器。 我已經更新了您的示例以使用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;
}
}
直接來自文檔:
要提供自定義錯誤處理,請實現ErrorListener接口並使用setErrorListener方法向Transformer注冊實現的實例。 然后,Transformer通過此界面報告所有錯誤和警告。
如果應用程序未注冊自己的自定義ErrorListener,則使用默認的ErrorListener向System.err報告所有警告和錯誤,並且不會拋出任何異常。 強烈建議應用程序注冊並使用ErrorListener,以確保警告和錯誤的正確行為。
對於轉換錯誤,Transformer必須使用此接口而不是拋出異常:由應用程序決定是否針對不同類型的錯誤和警告拋出異常。 但請注意,在調用fatalError(TransformerException異常)之后,Transformer不需要繼續轉換。
現在,在您的情況下,因為您的TransformThis
類正在實現ErrorListener。 您應該能夠使用以下內容轉換錯誤:
transformer.setErrorListener(this);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.