JAXB で DTD 妥当性検査をしたり、エンコーディングを指定したり

以下、テストケースを書くのに若干悩んだのと、忘れそうなのでメモ。

Jaxb2Marshaller のプロパティを指定する

Spring の Jaxb2Marshaller に対して、エンコードなど指定できる。

javax.xml.bind.Marshaller のサポートされているプロパティを参照

プロパティ 意味
jaxb.encoding XML データを整列化するときに使用される出力エンコーディング
jaxb.formatted.output Marshaller が改行とインデントを使用して結果として得られる XML データを書式設定するかどうかを制御
jaxb.schemaLocation xsi:schemaLocation 属性をクライアントアプリケーションが指定することができます
jaxb.noNamespaceSchemaLocation 生成 XML データの xsi:noNamespaceSchemaLocation 属性をクライアントアプリケーションが指定することができます
jaxb.fragment 文書レベルのイベントが Marshaller によって生成されるかどうかを決定します

 

設定ファイルでは、以下の様に上記プロパティを設定できる。

  1. <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  2. <property name="classesToBeBound">
  3. <list> .... </list>
  4. </property>
  5. <property name="marshallerProperties">
  6. <map>
  7. <entry>
  8. <key>
  9. <util:constant static-field="javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT" />
  10. </key>
  11. <value type="java.lang.Boolean">true</value>
  12. </entry>
  13. </map>
  14. </property>
  15. </bean>

動的にプロパティを変更する場合は、以下の様に setMarshallerProperties に設定できる。

  1. /**
  2. * ObjectをXML出力する
  3. * @param marshaller Jaxb2Marshaller のインスタンス
  4. * @param obj XML化するオブジェクト
  5. * @param encoding XMLのエンコーディング
  6. * @isFragment XML宣言を出力しない場合 true
  7. * @isFormatted 書式整形する場合 true
  8. */
  9. protected String objectToXml(Jaxb2Marshaller marshaller, Object obj, String encoding, boolean isFragment, boolean isFormatted){
  10. try {
  11. String fileEnc = "UTF-8";
  12. ByteArrayOutputStream os = new ByteArrayOutputStream();
  13. StreamResult result = new StreamResult(os);
  14. if (isFragment || isFormatted || (encoding != null)) {
  15. Map<String, Object> properties = new HashMap<String, Object>();
  16. if (encoding != null) {
  17. fileEnc = encoding;
  18. properties.put("jaxb.encoding", encoding);
  19. }
  20. if (isFragment) {
  21. properties.put("jaxb.fragment", Boolean.TRUE);
  22. }
  23. if (isFormatted) {
  24. properties.put("jaxb.formatted.output", Boolean.TRUE);
  25. }
  26. marshaller.setMarshallerProperties(properties);
  27. }
  28. marshaller.marshal(obj, result);
  29. return os.toString(fileEnc);
  30. }catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. }

DOCTYPEの出力

JAXBのアノテーションとかで、DOCTYPEの出力くらいできそうなものだが、どうやっていいかわからない。というかできなさそう。。。

ただ上記 Jaxb2Marshaller の jaxb.fragment プロパティは、JavaDoc にあるように、marshal(Object,OutputStream)や、marshal(Object,Writer) で呼び出した場合、XML 宣言を生成しない。

これを利用して、XML宣言と、DOCTYPE部分は自分で出力する。

Task は対象となるオブジェクト。dtd ファイルは、下記例では、c:\work\test\upload.dtd に実際にDTDファイルを置いておく。エンコーディングも指定している。

XML宣言と、DOCTYPEは自力で作成し、StringBuffer に突っ込んで、最終的なXMLを検査メソッドに渡す。

  1. Task task = new Task();
  2. String encode = "ISO-8859-1";
  3. String dtd = "file:///C:/work/test/upload.dtd";
  4. String type = Task.class.getSimpleName();
  5. boolean isFragment = true;
  6. String xmlFragment = objectToXml(imdsJaxb2Marshaller, task, encode, isFragment, true);
  7.  
  8. StringBuffer xml = new StringBuffer();
  9. xml.append(String.format("<?xml version=\"1.0\" encoding=\"%s\">\n",encode));
  10. xml.append(String.format("<!DOCTYPE %s SYSTEM \"%s\">\n",type, dtd));
  11. xml.append(xmlFragment);
  12.  
  13. dtdValidation(xml.toString());

DTDの妥当性検査

ここで、いろんなパターンの妥当性検査例サンプルがあるので参考に、dtdValidateion() メソッドを記述。

  1. protected void dtdValidation(String xml) {
  2. try {
  3. SAXParserFactory factory = SAXParserFactory.newInstance();
  4. factory.setValidating(true);
  5. factory.setNamespaceAware(true);
  6.  
  7. SAXParser parser = factory.newSAXParser();
  8.  
  9. XMLReader reader = parser.getXMLReader();
  10. reader.setErrorHandler(new SimpleErrorHandler());
  11. reader.parse(new InputSource(new StringReader(xml)));
  12. }catch(Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16.  
  17. private static class SimpleErrorHandler implements ErrorHandler {
  18. public void warning(SAXParseException e) throws SAXException {
  19. System.out.println(e.getMessage());
  20. }
  21.  
  22. public void error(SAXParseException e) throws SAXException {
  23. System.out.println(e.getMessage());
  24. }
  25.  
  26. public void fatalError(SAXParseException e) throws SAXException {
  27. System.out.println(e.getMessage());
  28. }
  29. }

いじょう。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です