CodeZine(コードジン)

特集ページ一覧

今からでも遅くない W3C XML Schemaを学ぼう!(前編)
難しいという固定観念を取り払う

まずは体験し、なぜ必要かを理解する

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2010/06/28 14:00

ダウンロード サンプルコード (3.9 KB)

目次

XML文書の妥当性検証

 XMLスキーマを使用してXML文書の妥当性を検証するには、JAXPのAPIを使用すると可能になります。ツールとして利用するには、XML文書やXMLスキーマ文書を指定できるように工夫することで実現できますが、今回は固定したファイルパスを使い妥当性を検証します。リスト3がJAXPを使ったXML文書を検証し結果を表示するためのプログラムです。

リスト3.MyXMLValidator.java
001:package jp.kawakubo.xmlschema;
002:
003:import java.io.IOException;
004:import java.io.PrintWriter;
005:import javax.servlet.ServletException;
006:import javax.servlet.http.HttpServlet;
007:import javax.servlet.http.HttpServletRequest;
008:import javax.servlet.http.HttpServletResponse;
009:import javax.xml.parsers.DocumentBuilder;
010:import javax.xml.parsers.DocumentBuilderFactory;
011:import org.xml.sax.ErrorHandler;
012:import org.xml.sax.SAXException;
013:import org.xml.sax.SAXParseException;
014:
015:public class MyXMLValidator extends HttpServlet {
016:
017:    private static final String SOURCE_PATH = "file:///Users/tomoharu/Documents/XMLSample/Meigara2.xml";
018:    private static final String XSD_PATH = "file:///Users/tomoharu/Documents/XSLSample/sample1.xsd";
019:   
020:    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
021:        throws ServletException, IOException {
022:        
023:        response.setContentType("text/html;charset=UTF-8");
024:        final PrintWriter out = response.getWriter();
025:
026:        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
027:        dbf.setValidating(true);
028:        dbf.setNamespaceAware(true);
029:        dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage" ,
030:                        "http://www.w3.org/2001/XMLSchema");
031:        dbf.setAttribute(
032:               "http://java.sun.com/xml/jaxp/properties/schemaSource", XSD_PATH);
033:
034:        DocumentBuilder db = null;
035:
036:        try {
037:            db = dbf.newDocumentBuilder();
038:        } catch ( javax.xml.parsers.ParserConfigurationException ex ) {
039:            System.err.println("DocumentBuilderの生成に失敗しました:" + ex.getMessage());
040:            return;
041:        }
042:
043:        db.setErrorHandler(new ErrorHandler() {
044:        // リスト4でErrorHandlerのメソッドを実装しています
045:        }
046:
047:         try {
048:             db.parse(SOURCE_PATH);
049:             try {
050:                out.println("<html>");
051:                out.println("<head>");
052:                out.println("<title>Servlet MyXMLValidator</title>");
053:                out.println("</head>");
054:                out.println("<body>");
055:                out.println("<h1>JAXPを使ってのXML文書の妥当性検証結果</h1>");
056:                out.println("<h2>正常終了</h2>");
057:                out.println("</body>");
058:                out.println("</html>");
059:            } finally {
060:                out.close();
061:            }
062:         } catch (SAXException e) {
063:             e.printStackTrace();
064:         }
065:
066:    } 
067:
068:    // HttpServlet のメソッドは紙面都合上割愛しています
069:
070:}

 26~32行目までのDocumentBuilderFactoryをインスタンス化し、フィールドに値を設定しているところが今回のJAXPの肝になります。28行目で名前空間を認識させ、29、30行目でスキーマ言語としてW3C XML Schemaの使用を指定しています。31、32行目でXMLスキーマ文書のパスを指定しています。

 次の肝が、34~45行目です。34~41行目でDocumentBuilderをインスタンス化しています。43行目でErrorHandlerを設定していますが、設定しなくても警告が出るのみです。ただし、今回のように、妥当性を検証するのにErrorHandlerがあるのに使用しないのはもったいない話です。ErrorHandlerを無名の内部クラスとして定義していますが、作り的に違和感がある方は適宜書き換えてください。

リスト4.ErrorHandlerのメソッドの実装
001:db.setErrorHandler(new ErrorHandler() {
002:    public void error(SAXParseException exception) {
003:        printResult(exception, "ERROR");
004:    }
005:
006:    public void fatalError(SAXParseException exception) {
007:        printResult(exception, "FATAL");
008:    }
009:
010:    public void warning(SAXParseException exception) {
011:        printResult(exception, "WARNING");
012:    }
013:
014:    private void printResult(SAXParseException exception, String category) {
015:        try {
016:            out.println("<html>");
017:            out.println("<head>");
018:            out.println("<title>Servlet MyXMLValidator</title>");
019:            out.println("</head>");
020:            out.println("<body>");
021:            out.println("<h1>JAXPを使ってのXML文書の妥当性検証結果</h1>");
022:            out.println("<table border='1'>");
023:            out.println("<tr>");
024:            out.println("<td>区分</td>");
025:            out.println("<td>"  + category + "</td>");
026:            out.println("</tr>");
027:            out.println("<tr>");
028:            out.println("<td>URI</td>");
029:            out.println("<td>"  + exception.getSystemId() + "</td>");
030:            out.println("</tr>");
031:            out.println("<tr>");
032:            out.println("<td>行</td>");
033:            out.println("<td>"  + exception.getLineNumber() + "</td>");
034:            out.println("</tr>");
035:            out.println("<tr>");
036:            out.println("<td>列</td>");
037:            out.println("<td>"  + exception.getColumnNumber() + "</td>");
038:            out.println("</tr>");
039:            out.println("<tr>");
040:            out.println("<td>メッセージ</td>");
041:            out.println("<td>"  + exception.getMessage() + "</td>");
042:            out.println("</tr>");
043:            out.println("</table>");
044:            out.println("</body>");
045:            out.println("</html>");
046:        } finally {
047:            out.close();
048:        }
049:    }
050:
051:});

 この無名内部クラスで難しい部分はありません。ErrorHandlerにはerror、fatalError、warningの3つがあります。それぞれ引数としてSAXParseExceptionを取ります。3つのメソッドで引数が同じのためprintResultというメソッドを用意し、exceptionがERRORかFATAL ERRORか WARNINGか識別できるよう第2引数に設定しています。

 printResultの内容は単にSAXParseExceptionのメソッドである、getSystemId、getLineNumber、getColumnNumberと継承しているSAXExceptionのメソッドであるgetMessageメソッドを使用し表示しているのみです。

 面白いのはXML文書だけでなくXMLスキーマ文書の間違いも例外として補足され表示されることです。従って、スキーマを作成したもののスキーマ自体の妥当性が分からないという場合も、このツールが使用できます。つまり、W3C XML Schema自体にもスキーマが存在すればこそできることです。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:今からでも遅くない、W3C XML Schemaを学ぼう!

著者プロフィール

  • 川久保 智晴(カワクボ トモハル)

    haruプログラミング教室(https://haru-idea.jp/)主宰。 COBOL、FORTRANで13年、Javaを中心としたWeb開発で11年。3つしか言語知らないのかというとそうでもなく、sed/awk、Perl、Python, PHP, &nbsp;C#, JavaScript...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5