XMLスキーマ検証の方法

XMLのスキーマ検証方法について、いくつかまとめてみました。

- `javax.xml.validation.Validator`の`validate(Source source)`を利用する方法
- `org.xml.sax.XMLReader` の`parse(InputSource source)`を利用する方法
- `javax.xml.parsers.SAXParser` の`parse(InputSource is, DefaultHandler dh)`を利用する方法
- `javax.xml.parsers.DocumentBuilder` の`parse(InputSource source)`を利用する方法
- JAXBのアンマーシャル（Unmarshal）を利用する方法


# javax.xml.validation.Validatorの利用

`javax.xml.validation.Validator`のメソッド`validate(Source source)`を利用する場合の実装例です。

```java
/**
 * スキーマ検証
 */
private void schemaValidate(String xmlStr) {
		
	SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

	try {
		// Schema インスタンスを生成
		Schema schema = factory.newSchema(new File("/WSDL/ProductInput.xsd"));
		// Validator インスタンスを生成
		Validator validator = schema.newValidator();

		// 妥当性検証を実行
		validator.validate(new StreamSource(new StringReader(xmlStr)));
			
	} catch (SAXException | IOException e) {
		throw new RuntimeException(e);
	}
}
```

# org.xml.sax.XMLReaderの利用

`org.xml.sax.XMLReader` のメソッド`parse(InputSource source)`を利用する場合の実装例です。

```java
/**
 * スキーマ検証
 */
private void schemaValidate(String xmlStr) {
		
	try {
		// XMLReader インスタンの作成
		XMLReader reader = XMLReaderFactory.createXMLReader();

		// スキーマ検証エラー発生時のエラーハンドラ
		reader.setErrorHandler(new MySaxErrorHandler());

		// 妥当性検証を有効にする。	
		reader.setFeature("http://xml.org/sax/features/validation", true);
		// XML Schemaによる妥当性検証を有効にする。
		reader.setFeature("http://apache.org/xml/features/validation/schema", true);
		// ネームスペースの認識を有効にする。
		reader.setFeature("http://xml.org/sax/features/namespaces", true);
		// ネームスペースの接頭辞の認識を有効にする。
		reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
			
		// XML Schemaの仕様に従って検証を行うことを示す値，"http://www.w3.org/2001/XMLSchema"を設定する。
		reader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", XMLConstants.W3C_XML_SCHEMA_NS_URI);
		// 検証に使うスキーマ文書を指定する。
		reader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", new File("/WSDL/ProductInput.xsd"));
		
		// 妥当性検証を実行
		reader.parse(new InputSource(new StringReader(xmlStr)));
			
	} catch (SAXException | IOException e) {			
		throw new RuntimeException(e);
	}
}
```

# javax.xml.parsers.SAXParserの利用

`javax.xml.parsers.SAXParser` のメソッド`parse(InputSource is, DefaultHandler dh)`を利用する場合の実装例です。

```java
/**
 * スキーマ検証
 */
private void schemaValidate(String xmlStr) {
	
	SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
	SAXParserFactory saxFactory = SAXParserFactory.newInstance();
		
	try {
		// Schema インスタンスを生成
		Schema schema = schemaFactory.newSchema(new File("/WSDL/ProductInput.xsd"));
		
		// SAXParserFactory にschemaの設定
		saxFactory.setSchema(schema);
		//　ネームスペースの認識を有効にする。
		saxFactory.setNamespaceAware(true);

		// SAXParser インスタンスを生成
		SAXParser parser = saxFactory.newSAXParser();
		// スキーマ検証エラー発生時のエラーハンドラ
		DefaultHandler myHandler = new MySaxErrorHandler();
		
		// 妥当性検証を実行
		parser.parse(new InputSource(new StringReader(xmlStr)), myHandler);
			
	} catch (SAXException | ParserConfigurationException | IOException e) {
		throw new RuntimeException(e);
	}
}
```

# javax.xml.parsers.DocumentBuilderの利用

`javax.xml.parsers.DocumentBuilder` のメソッド`parse(InputSource source)`を利用する場合の実装例です。

```java
/**
 * スキーマ検証
 */
private Document schemaValidate(String xmlStr) {
	
	DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();

	try {
		// XML Schemaによる妥当性検証を有効にする。
		docFactory.setValidating(true);
		//　ネームスペースの認識を有効にする。
		docFactory.setNamespaceAware(true);

		// XML Schemaの仕様に従って検証を行うことを示す値，"http://www.w3.org/2001/XMLSchema"を設定する。
		docFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", XMLConstants.W3C_XML_SCHEMA_NS_URI);
		// 検証に使うスキーマ文書を指定する。
		docFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", new File("/WSDL/ProductInput.xsd"));

		// DocumentBuilder インスタンスの生成
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
		// スキーマ検証エラー発生時のエラーハンドラ
		docBuilder.setErrorHandler(new MySaxErrorHandler());

		// 妥当性検証を実行し、Documetオブジエンドに変換する。
		Document doc = docBuilder.parse(new InputSource(new StringReader(xmlStr)));

		return doc;

	} catch (ParserConfigurationException | SAXException | IOException e) {
		throw new RuntimeException(e);
	}
}
```

#JAXBのアンマーシャル（Unmarshal）を利用する方法

JAXBでスキーマ検証を行う場合の実装例です。

```java
/**
 * スキーマ検証
 */
private ProductInput schemaValidate5(String xmlStr) {
	
	ProductInput input = null;
	Unmarshaller unmarshaller;
		
	SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		
	try {
		// Schema インスタンスを生成
		Schema schema = schemaFactory.newSchema(new File("/WSDL/ProductInput.xsd"));
		// JAXBContext インスタンスを生成
		JAXBContext jc = JAXBContext.newInstance(ProductInput.class.getPackage().getName());

		// Unmarshaller インスタンスを生成
		unmarshaller = jc.createUnmarshaller();	
		// Unmarshaller にschema の設定
		unmarshaller.setSchema(schema);

		// スキーマ検証を実行
		input = (ProductInput)unmarshaller.unmarshal(new InputSource(new StringReader(xmlStr)));
			
	} catch (JAXBException | SAXException e) {
		throw new RuntimeException(e);
	}
		
	return input;
}
```