2023. 1. 12. 20:56ㆍJava
프로젝트 내 src 내 xml 패키지 내 test03.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="제목">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="가격" type="xsd:positiveInteger"/>
<xsd:element name="사이즈" type="xsd:double"/>
<xsd:element name="이미지">
<xsd:complexType>
<xsd:attribute name="src" type="xsd:anyURI"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="컬러">
<xsd:complexType>
<xsd:attribute name="빨강색" type="xsd:unsignedByte"/>
<xsd:attribute name="노란색" type="xsd:unsignedByte"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
프로젝트 내 src 내 xml 패키지 내 test031.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
<제목 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="file:/D:/javaddazua/java_xml/src/xml/test03.xsd">
-->
<!-- 스키마문서 지운상태로 만들기 지난번에 만든 ValidateXmlApp을 수행해본다 이러한
문서들이 실제로 많다 응용프로그램 자체에서 xsd 를 만들어서 유효성 검사 패키지를 알아야 한다 -->
<제목 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<가격>1000</가격>
<사이즈>65.45</사이즈>
<이미지 src="/xml/test/book.gif"/>
<컬러 빨강색="201" 노란색="255"/>
</제목>
xml에서 xmlns의 의미
[출처] xmlns, xmlns:xsi 이란?|작성자 동시사랑
============================================================================================
프로젝트 내 src 내 java_xml 패키지 내 ValidateXmlApp.java
package java_xml;
import org.xml.sax.InputSource;
public class ValidateXmlApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
boolean isValid = false;
InputSource srcXml = new InputSource("src/xml/test031.xml");
isValid = ValidateApp.validateXml(srcXml);
//유효성 검사 후의 문서 처리코드
if(isValid) {
System.out.println("유효한 문서입니다.");
} else {
System.out.println("유효하지 않는 문서 입니다.");
}
}
}
============================================================================================
프로젝트 내 src 내 java_xml 패키지 내 ValidateXmlXsd.java
package java_xml;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
public class ValidateXmlXsd {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// 스키마 문서가 없으므로 스키마 문서를 로딩해서 동적으로 유효성 검사위한 패키지 필요
/*
* 동적으로 스키마문서를 로딩해서 XML 문서의 유효성 검사를 하기위해서는
* javax.xml.validation 패키지를 이용한다.
*
* 세 개의 클래스로 유효성 검사하기
* - SchemaFactory : 동적으로 XML스키마 문서 객체를 생성
* - Schema : 동적으로 생성된 XML 스키마 객체
* - Validator : 스키마 객체를 가지고 유효성 검사를 하는 객체
*
* ValidateApp.java 클래스를 보강하러가기
*
* 스키마팩토리 생성
* --> SchemaFactory.newInstance(String schemaLanguage);
*
* 스키마 생성 세가지 형태
* 단일스키마문서
* --> schemaFactory.newSchema(File schema);
* --> schemaFactory.newSchema(Source schema);
* 여러개의어떤스키마문서로딩할경우
* --> schemaFactory.newSchema(Source[] schema);
*
* Validator 생성(유효성검사하는)
* -->schema.newValidator();
*
* 최종으로 등록하기
* 에러이벤트핸들러 처리할 수 있도록 등록해주는 과정이 필요하다
* 에러핸들러 구현 객체를 등록
* --> setErrorHandler(new ValidateApp());
*
* 마지막으로 검사 유효성 검사
* --> Validator.validate(Source src);
*
* ValidateApp.java 로 가서 메서드 작성하기
* validateXmlSchema 메서드를 불러오기만 하면 된다
*/
boolean isValid = false;
Source srcXml = new StreamSource("src/xml/test031.xml");
//로딩해서 소스객체를 하나 만들어준것
Source[] srcXsd = new Source[] {
new StreamSource("src/xml/test03.xsd")
};
isValid = ValidateApp.validateXmlSchema(srcXml, srcXsd);
//유효성 검사 후의 문서 처리코드
if(isValid) {
System.out.println("유효한 문서입니다.");
} else {
System.out.println("유효하지 않는 문서 입니다.");
}
}
}
// XML Path Language(XPath)
// Path 경로, 각각의 태그들로 이루어져 있죠. XPath를 이용하면 태그를 쉽게 접근할수있다
// XPath 랭귀지로 경로를 지정해서 찾아갈 수 있다. 속성이나 엘리먼트를 접근할 수 있다.
// 접근하기 위해서 만들어놓은 언어
// XML문서에서 특정 엘리먼트나 속성에 접근하기 위해 경로를 지정하는 언어
// XSLT언어와 Xpointer언어에서 사용
// XPath가 없다면. XSLT와 XPath로 이루어진 언어.
// XSL을 사실상 작성할 수가 없다. 필수적인 요소 언어 XPath으로 XSL문서의 필수적인 언어이다
// 절대경로 "/"로 시작
// 상대 경로 ".", ".." 를 사용
위에서
Source[] srcXsd = new Source[] { new StreamSource("src/xml/test03.xsd") };
부분은 많이 써보지 않은 형태인데
배열 선언시에
int[] list = new int[]{10,20,30,40,50};
와 같이
배열을 선언하면서 동시에 배열을 생성하는 모양새이다.
밑에 설명에서 XML Path Language(XPath)를 다음 코드에서 볼 수 있다.
======================================================
XpathTest.java
package java_xml;
import javax.xml.xpath.*;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class XpathTest {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
/*
* 자바에서 제공하고있는 패키지
* 자바에서는 Xpath로 XML문서를 검색하기 위해서
* javax.xml.xpath패키지에서 제공하는 XPath 인터페이스를 구현한 클래스를 생성해야한다.
*
* XPathFactory xpathFactory = XPathFactory.newInstance();
* XPath xpath = xpathFactory.newXPath();
*
* XPath에서 제공하는 evaluate() 메소드를 이용해서 검색가능
*
* 반환타입이 문자열인 경우.우리가검색하고자하는것이문자열일경우와 객체타입으로반환하는타입으로 두가지
* 스트링:단일값반환하는경우,해당속성값이라든지.책이라는엘리먼트안에제목이있다고가정하면
* 제목이라는엘리먼트.내용부.컨텐트.문자데이타.엘리먼트에 대한 내용을 가져오거나 할때
* 책의 여러가지 속성 중 분류다그럼 이 속성에대한 값을 갖고오고자할때 해당값,단일값을 가져올수있다.
*
* 오브젝트형 반환하는 경우:검색대상자체가 노드이다.노드(태그)라든지 노드리스트(여러개의엘리먼트).
* 책에 엘리먼트 수만큼 가져올수있는데 이땐 오브젝트형태로반환하자는거죠
*
* expression은 XPath에 대한 표현식이다.
* 절대경로로 표시한다면 /는 최상위루트엘리먼트
* InputSource 일반 XML 문서의 위치 뚀는 돔 또는 스트림형태
*
* Object item은 노드형태로 입력하고자 할때 오브젝트 타입으로 사용
*
* QName은 리턴타입이다. 검색대상자체가 노드이므로 해당 노드 타입.여러개거나
* 단일 엘리먼트일 경우 그 엘리먼트에 대한 객체타입을 지정해 주는것. 자바상수.
* 리턴하게될 큐네임 타입을 지정하는 인자다
*
* 큐네임은 각엘리먼트에서 접두어와 해당 엘리먼트 이름을 큐네임이라 한다
* 큐네임에 대한 해당 엘리먼트에 대한 리턴타입이 된다.
*
* String evaluate(String expression, InputSource source)
* String evaluate(String expression, Object item)
* Object evaluate(String expression, InputSource source, QName returnType)
* Object evaluate(String expression, Object item, QName returnType)
*
* 큐네임 객체와 형변환 가능한 자바 객체형
* Qname 객체
* java.xml.xpath패키지안에 XPathConstants라고 하는 상수를 이용해서 큐네임
* 객체를 표기한다
*
* evaluate로 해당 xml문서를 검색할텐데...
*
* evaluate의 반환타입이 된다.
* XPathConstants.BOOLEAN -> java.lang.Boolean
* XPathConstants.NODE -> org.w3c.dom.Node
* XPathConstants.NODESET 여러개의 엘리먼트일 경우 리스트형태로 값을 보냄 -> org.w3c.dom.NodeList로 형변환해줘야
* XPathConstants.NUMBER 각 엘리먼트(큐네임)의 수 -> java.lang.Double
* XPathConstants.STRING 문자열형태로 보내줄수있다 -> java.lang.String
*
*
*/
//XPath 객체 생성
XPathFactory xfactory = XPathFactory.newInstance();
XPath xpath = xfactory.newXPath();
//XML 원본에 대한 InputSource 객체 생성
InputSource xmlSrc = new InputSource("src/xml/test02.xml");
System.out.println("==== 아이디(책의속성)를 이용한 검색 ====");
//id는 속성 책의 속성. 도서리스트가 최상위 루트 엘리먼트.
//도서리스트 전에 최상위 루트 엘리먼트는 슬래쉬 / 로 시작하고
//슬래쉬 밑에 도서리스트가 있다 도서리스트 밑에 책이있다
//책이 하나 둘 세개 있다. 도서리스트에는
//똑같은 자식이 세명있는 거다. 책 밑에 여러개 자식들있다
//책에 대한 각각의 제목,저자,출판사,가격,이미지,소개가 있다.
//책에는 분류와 id라는 속성이 있다. 노드(돔트리)=엘리먼트, 같은 레벨의 자식들이 노드셋이다(자바에서는 노드셋을 노드리스트로 변환한다)
//책을 표현하면 밑에처럼 XPath 표현식이 된다
// /도서리스트/책
// 해당 속성에 대한 표시는 대괄호 [@속성명]
String title = xpath.evaluate("/도서리스트/책/제목[../@id='book1']", xmlSrc);
System.out.println(title);
System.out.println("==== 아이디로 책 엘리먼트 찾아오기 ====");
//이경우 엘리먼트가 반환되니 반환타입은 오브젝트가 된다, 각 엘리먼트=노드
//반환타입이 노드이다
Node nBook = (Node)xpath.evaluate("/도서리스트/책[@id='book2']", xmlSrc, XPathConstants.NODE); //아이디가 book2인 책 엘리먼트를 구하겠다 반환타입을 맞춘다.형변환
//엘리먼트객체 책
Element bookElement = (Element) nBook;
//이 nBook에 대한 해당 속성을 구해오면 두번째 엘레먼트에 대한 분류값이 소설이므로 소설인지 아닌지 확인하면 두번째 노드를 구해온걸 정확히 확인가능
System.out.println(bookElement.getAttribute("분류"));
//책이 총 엘리먼트 수가 몇개인가
System.out.println("===== 책 엘리먼트의 수 =====");
Double bookCnt = (Double)xpath.evaluate("count(/도서리스트/책)", xmlSrc, XPathConstants.NUMBER);
System.out.println(bookCnt);
//노드리스트,노드셋형태 반환,책 제목 모두 출력
System.out.println("===== 모든 책 제목 =====");
NodeList bookList = (NodeList)xpath.evaluate("/도서리스트/책/제목", xmlSrc, XPathConstants.NODESET);
System.out.println(bookList.getLength());
for (int i = 0 ; i < bookList.getLength() ; i = i + 1) {
Element titleElement = (Element) bookList.item(i);
System.out.println(titleElement.getTextContent());
}
}
}
//evaluate는 매번 사용하지만 compile 메소드를 사용하면 여러번 자료를 사용할 수 있어요
=========================================
=================================================================================
프로젝트 내 src 내 java_xml 패키지 내 ValidateApp.java
package java_xml;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
//error 이벤트핸들러
//xml 문서 파싱 시 밸리데이터 앱에 있는 우리가 만들려고 하는 xml 문서에 외부스키마 문서가
//있을 때 파싱할수있는 메서드를 가지고 있다면 정상적으로 만들어져있다면 result를 트루로
//만들자는 거죠.true라면 현재 xml 문서가 유효하다는 것을 판정하자는 겁니다.
//xml문서가 스키마문서가있는경우.xml문서만 바로 유효성검사하면되고
//스키마문서없으면 xsd라는 객체를 만들어서 해줘야 하고
public class ValidateApp implements ErrorHandler {
private static boolean result;
public void error(SAXParseException arg0) throws SAXException {
//에러발생시 결과는 false
ValidateApp.result = false;
}
public void fatalError(SAXParseException arg0) throws SAXException {
ValidateApp.result = false;
}
public void warning(SAXParseException arg0) throws SAXException {
}
//스키마 문서가 지정되어 있는 경우의 유효성 검사 메소드
public static boolean validateXml(InputSource srcXml) {
ValidateApp.result = true;
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/validation/schema", true); //스키마문서를 해석하기 위해 uri를 적어야한다 유효성 검사하기위해서
SAXParser parser = factory.newSAXParser(); // 참조인스턴스를 parser
XMLReader reader = parser.getXMLReader();
// 이벤트핸들러는 에러핸들러인터페이스를 구현한 ValidateApp이라는 현클래스가 된다
reader.setErrorHandler(new ValidateApp());
reader.parse(srcXml);
} catch (Exception e) {
// 파싱시 문제발생시 리절트값을 폴스로
ValidateApp.result = false;
// 응용프로그램에서 이 validateXml 메소드를 사용하게 될테니깐
// return 값이 폴스로 오게 된다면 유효하지 않거나
}
return ValidateApp.result;
}
//스키마 문서가 지정되지 않은 문서의 유효성 검사 메소드-스키마와XML동시에확인하는메서드
//이 메서드 작성 후 다시 ValidateXmlXsd.java 로 간다
public static boolean validateXmlSchema(Source srcXml, Source[] srcXsd) {
ValidateApp.result = true;
try {
//팩토리생성,스키마객체얻어오는과정
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(srcXsd);
Validator validator = schema.newValidator(); //schema객체를 통해 만듦
validator.setErrorHandler(new ValidateApp());
validator.validate(srcXml);
//여기까지 쓰고 ValidateXmlXsd.java로 간다
} catch (Exception e) {
ValidateApp.result = false;
}
return ValidateApp.result;
}
}
'Java' 카테고리의 다른 글
Java XML - XSL 변환기 생성 - TransformerFactory, Transformer (0) | 2023.01.12 |
---|---|
Java XML - XML문서 파일로 저장하기 (0) | 2023.01.12 |
Java XML setData(), setAttribute() (0) | 2023.01.12 |
Java XML startElement(), characters(), endElement() (1) | 2023.01.12 |
Java XML ContentHandler (0) | 2023.01.12 |