本来はこういう使い方はしないんだろうけど、SaxonをDTDバリデータとして使ってみる。Saxonは8.7.
// 対象となるXML String xml = "<?xml....."; // 何もしないXSL String noopXsl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"2.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"></xsl:stylesheet>"; try { StreamSource xslSource = new StreamSource(new ByteArrayInputStream(noopXsl.getBytes("UTF-8"))); StreamSource xmlSource = new StreamSource(new ByteArrayInputStream(xml.getBytes("UTF-8"))); /// エラー時の出力をByteArrayOutputStreamで受けるようなSaxonのFactoryクラスを作成する // factoryの設定を行うObjectを作成 Configuration saConfig = new net.sf.saxon.Configuration(); // エラーリスナーのOutputする先をバイトストリームにする StandardErrorListener se = new net.sf.saxon.StandardErrorListener(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); // Objectをセット se.setErrorOutput(ps); saConfig.setErrorListener(se); // factory作成 TransformerFactory tFactory = new net.sf.saxon.TransformerFactoryImpl(saConfig); /** * ファクトリのDTDチェックをONにする。設定できるものは、net.sf.saxon.FeatureKeysにありそう */ tFactory.setAttribute(FeatureKeys.DTD_VALIDATION, true); Transformer transformer = tFactory.newTransformer(xslSource); transformer.transform(xmlSource, new StreamResult(new StringWriter())); // baos.size()が0ならDTDエラーは無い。 if (baos.size() > 0){ System.out.println(baos); } baos.close(); ps.close(); } catch (UnsupportedEncodingException ex) { } catch (TransformerConfigurationException ex) { } catch (TransformerException ex) { } catch (IOException ex) { }
tFactory.setAttribute()で何が使えるかというと、Saxonをコマンドラインで動かしてみて
$ java -jar saxonb9/saxon9.jar No source file name Saxon 9.1.0.8J from Saxonica Usage: see http://www.saxonica.com/documentation/using-xsl/commandline.html Options: -a Use xml-stylesheet PI, not style-doc argument -c:filename Use compiled stylesheet from file -cr:classname Use collection URI resolver class -dtd:on|off Validate using DTD -expand:on|off Expand defaults defined in schema/DTD -explain[:filename] Display compiled expression tree -ext:on|off Allow|Disallow external Java functions -im:modename Initial mode -it:template Initial template -l:on|off Line numbering for source document -m:classname Use message receiver class -o:filename Output file or directory -or:classname Use OutputURIResolver class -outval:recover|fatal Handling of validation errors on result document -p:on|off Recognize URI query parameters -r:classname Use URIResolver class -repeat:N Repeat N times for performance measurement -s:filename Initial source document -sa Schema-aware transformation -strip:all|none|ignorable Strip whitespace text nodes -t Display version and timing information -T[:classname] Use TraceListener class -TJ Trace calls to external Java functions -tree:tiny|linked Select tree model -traceout:file|#null Destination for fn:trace() output -u Names are URLs not filenames -val:strict|lax Validate using schema -versionmsg:on|off Warn when using XSLT 1.0 stylesheet -warnings:silent|recover|fatal Handling of recoverable errors -x:classname Use specified SAX parser for source file -xi:on|off Expand XInclude on all documents -xmlversion:1.0|1.1 Version of XML to be handled -xsd:file;file.. Additional schema documents to be loaded -xsdversion:1.0|1.1 Version of XML Schema to be used -xsiloc:on|off Take note of xsi:schemaLocation -xsl:filename Stylesheet file -y:classname Use specified SAX parser for stylesheet -? Display this message param=value Set stylesheet string parameter +param=filename Set stylesheet document parameter !option=value Set serialization option
これらのOptionなら設定できそうである。
Saxonを9.7にしてみる
Saxon9.7にすると、上記の方法だとエラーが出る。
主にエラー出力のハンドリング回り。
// この2つはlibのパッケージは以下になった import net.sf.saxon.lib.FeatureKeys; import net.sf.saxon.lib.StandardErrorListener; // Loggerクラスを備えるようになった。 import net.sf.saxon.lib.StandardLogger; ... StandardErrorListener se = new StandardErrorListener(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); se.setLogger(new StandardLogger(ps)); // se.setErrorOutput(ps); se.setLogger(new StandardLogger(ps));
StandardErrorListenerの方向をsetErrorOutputではなく、setLoggerメソッドでLoggerオブジェクトを渡すことで設定する。