4

javax.xml.transform.*XSLT変換を行うために使用しています。使用する xslt ファイルは外部からのものであるため、そのファイルにエラーがある可能性があります。ユーザーに意味のある応答を返します。

sは簡単にキャッチできますがTransformationException、そこから十分な情報を取得する方法が見つかりませんでした。たとえば、終了タグで終了するタグがある場合、printStackTrace()scarring メッセージが表示されます

javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Unknown Source)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(Unknown Source)
    ... (100 lines)

そしてgetMessage()与えるだけ

Could not compile stylesheet

エラーの本当の理由を示すものはありません。

Eclipse テスト コンソールで次のように表示されることに気付きました

[Fatal Error] :259:155: The element type "sometag" must be terminated by the matching end-tag "</sometag>".
ERROR:  'The element type "sometag" must be terminated by the matching end-tag "</sometag>".'
FATAL ERROR:  'Could not compile stylesheet'

これはまさに私が欲しいものです。残念ながら、これは Web アプリケーションであるため、ユーザーはこれを見ることができません。

ユーザーに正しいエラー メッセージを表示するにはどうすればよいですか?

4

3 に答える 3

1

次のように、を使用ErrorListenerしてTransformerインスタンスに独自のものを配置します。Transformer.setErrorListener

final List<TransformationException> errors = new ArrayList<TransformationException>();
Transformer transformer = ... ;
transformer.setErrorListener(new ErrorListener() {

    @Override
    public void error(TransformerException exception) {
        errors.add(exception);
    }

    @Override
    public void fatalError(TransformerException exception) {
        errors.add(exception);
    }

    @Override
    public void warning(TransformerException exception) {
        // handle warnings as well if you want them
    }
});

// Any other transformer setup

Source xmlSource = ... ;
Result outputTarget = ... ;
try {
    transformer.transform(xmlSource, outputTarget);
} catch (TransformerException e) {
    errors.add(e); // Just in case one is thrown that isn't handled
}
if (!errors.isEmpty()) {
    // Handle errors
} else {
    // Handle output since there were no errors
}

これにより、発生したすべてのエラーがerrorsリストに記録され、それらのエラーからのメッセージを使用して必要なものを取得できます。これには、エラーが発生した後に変換を再開しようとするという追加の利点があります。これにより問題が発生した場合は、次のようにして例外を再スローします。

@Override
public void error(TransformerException exception) throws TransformationException {
    errors.add(exception);
    throw exception;
}

@Override
public void fatalError(TransformerException exception) throws TransformationException {
    errors.add(exception);
    throw exception;
}
于 2013-09-05T06:30:21.740 に答える
0

まず、どのソリューションも XSLT プロセッサの選択に依存する可能性があります。JAXP インターフェースの実装が異なれば、生成される例外で異なる情報が提供されることもあります。

XML パーサーからのエラーは、ラップされた例外で使用できる可能性があります。歴史的な理由から、TransformerConfigurationException はラップされた例外にアクセスするために getException() と getCause() の両方を提供しており、両方をチェックする価値があるかもしれません。

または、ErrorListener への別の呼び出しで情報が提供された可能性があります。

最後に、この特定のエラーは (XSLT プロセッサではなく) XML パーサーによって検出されるため、最初のインスタンスではパーサーによって処理されます。パーサーの ErrorHandler を設定し、そのレベルで解析エラーをキャッチする価値があるかもしれません。変換で使用される XML パーサーを明示的に制御する必要がある場合は、XMLReader が適切に初期化されている SAXSource を使用します。

于 2013-09-05T08:29:54.790 に答える
-1

独自の OutputStream に書き込むように System.out を構成できます。ErrorListener を使用しても、すべての出力がキャッチされるわけではありません。スレッドを扱う場合は、ここ ( http://maiaco.com/articles/java/threadOut.php ) を参照して、他のスレッドの System.out の変更を回避できます。

public final class XslUtilities {
    private XslUtilities() {
        // only static methods
    }

    public static class ConvertWithXslException extends Exception {
        public ConvertWithXslException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    public static String convertWithXsl(String input, String xsl) throws ConvertWithXslException {
        ByteArrayOutputStream systemOutByteArrayOutputStream = new ByteArrayOutputStream();
        PrintStream oldSystemOutPrintStream = System.out;
        System.setOut(new PrintStream(systemOutByteArrayOutputStream));

        ByteArrayOutputStream systemErrByteArrayOutputStream = new ByteArrayOutputStream();
        PrintStream oldSystemErrPrintStream = System.err;
        System.setErr(new PrintStream(systemErrByteArrayOutputStream));

        String resultXml;
        try {
            System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer(new StreamSource(new StringReader(xsl)));
            StringWriter stringWriter = new StringWriter();
            transformer.transform(new StreamSource(new StringReader(input)), new StreamResult(stringWriter));
            resultXml = stringWriter.toString();
        } catch (TransformerException e) {
            System.out.flush();
            final String systemOut = systemOutByteArrayOutputStream.toString();
            System.err.flush();
            final String systemErr = systemErrByteArrayOutputStream.toString();

            throw new ConvertWithXslException("TransformerException - " + e.getMessageAndLocation()
                            + (systemOut.length() > 0 ? ("\nSystem.out:" + systemOut) : "")
                            + (systemErr.length() > 0 ? ("\nSystem.err:" + systemErr) : ""), e);
        } finally {
            System.setOut(oldSystemOutPrintStream);
            System.setErr(oldSystemErrPrintStream);
        }

        return resultXml;
    }
}
于 2013-09-05T06:37:30.077 に答える