2017-12-04 18 views
0

XML 파일과 해당 XSD 파일이 있습니다. StAX 파서를 사용하여 유효성을 검사하는 동안 오류 처리기를 첨부했습니다. 기본적으로 올바른 형식의 XML 파일에서 두 가지 유형의 오류가 발생합니다.XSD에 대해 유효성을 검사하는 동안 DOM, StAX, SAX 파서 중 하나를 사용하여 XML에서 정확한 누락 요소를 찾습니다.

1) 요소 내에 잘못된 유형의 데이터가 있습니다 (예 : 정수가 있어야하는 요소 내부의 문자열).

2) 누락 요소 : XSD에 따라 있어야하는 요소가 XML에 없습니다.

StAX 구문 분석기 및 사용자 지정 오류 처리기를 사용하여 첫 번째 오류 유형을 수정할 수 있습니다. 그러나 두 번째 유형의 경우 CHARACTER 이벤트가 트리거되고 TEXT 값은 바로 다음 요소의 값입니다. 누락 된 요소를 파악하는 방법을 모르겠습니다. 또한 CHARACTER 이벤트가 트리거되고 누락 된 요소가 완전히 무시되는 이유는 무엇입니까?

StAX 파서는 앞으로 만 진행되므로 다른 파서를 사용하여 두 가지 오류를 모두 해결할 수있는 방법이 있습니까?

<?xml version="1.0" encoding="UTF-8"?> 
<PHSHumanSubjectsAndClinicalTrialsInfo:PHSHumanSubjectsAndClinicalTrialsInfo xmlns:PHSHumanSubjectsAndClinicalTrialsInfo="http://apply.grants.gov/forms/PHSHumanSubjectsAndClinicalTrialsInfo-V1.0" PHSHumanSubjectsAndClinicalTrialsInfo:FormVersion="1.0" 
> 
<!-- <PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator 
    >Y: </PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator 
    >--> 
    <PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator1 
    >Y: Yes</PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator1 
    > 
    <PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator2 
    >Y: Yes</PHSHumanSubjectsAndClinicalTrialsInfo:HumanSubjectsIndicator2 
    > 
다음

HumanSubjectsIndicator 요소가 두 번째 시나리오를 자극 주석 :

import java.io.File; 
import java.io.IOException; 
import javax.xml.XMLConstants; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamConstants; 
import javax.xml.stream.XMLStreamException; 
import javax.xml.stream.XMLStreamReader; 
import javax.xml.transform.stax.StAXSource; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.*; 
import javax.xml.validation.Validator; 
import org.xml.sax.ErrorHandler; 
import org.xml.sax.SAXException; 
import org.xml.sax.SAXParseException; 

public class XMLValidation { 

    public static void main(String[] args) { 

     XMLValidation xmlValidation = new XMLValidation(); 
     System.out.println(xmlValidation.validateXMLSchema("PHSHumanSubjectsAndClinicalTrialsInfo-V1.0.xsd", "FullPHSHuman.xml")); 
    } 

    public boolean validateXMLSchema(String xsdPath, String xmlPath){ 

     try { 
      SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
      Schema schema = factory.newSchema(new File(xsdPath)); 
      StreamSource XML = new StreamSource(xmlPath); 
      XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(XML); 
      Validator validator = schema.newValidator(); 
      validator.setErrorHandler(new MyErrorHandler(reader)); 
      validator.validate(new StAXSource(reader)); 
     } catch (IOException | SAXException | XMLStreamException e) { 
      System.out.println("Exception: "+e.getMessage() + " local message " + e.getLocalizedMessage() + " cause " + e.getCause()); 
      return false; 
     } 
     return true; 
    } 
} 

class MyErrorHandler implements ErrorHandler { 

    private XMLStreamReader reader; 

    public MyErrorHandler(XMLStreamReader reader) { 
     this.reader = reader; 
    } 

    @Override 
    public void error(SAXParseException e) throws SAXException { 
     System.out.println("error"); 
     warning(e); 
    } 

    @Override 
    public void fatalError(SAXParseException e) throws SAXException { 
     System.out.println("fatal error"); 
     warning(e); 
    } 

    @Override 
    public void warning(SAXParseException e) throws SAXException { 
     if(reader.getEventType() == 1 || reader.getEventType() == 2) { 
      //The first type of error is detected here. 
      System.out.println(reader.getLocalName()); 
      System.out.println(reader.getNamespaceURI()); 

     } 

     if(reader.getEventType() == XMLStreamConstants.CHARACTERS) { 
      int start = reader. getTextStart(); 
      int length = reader.getTextLength(); 
      System.out.println(new String(reader.getTextCharacters(), start, length)); 
     } 
    } 
} 

아래는 잘 구성된 XML 파일의 조각입니다. 이 경우 'MyErrorHandler'에서 CHARACTER 이벤트가 트리거됩니다. 'Y : Yes'값은 reader.getTextCharacters()에서 가져옵니다. 이 값은 HumanSubjectsIndicator1 요소에 해당합니다 (getLocation() 메소드를 사용하여이 값을 찾습니다).

누락 된 요소의 로컬 이름을 정확하게 가져 오는 방법이 있습니까? StAX를 사용하지 않는다면 다른 파서를 사용 하시겠습니까?

감사합니다. 필요한 요소가 없을 때

답변

1

색슨 XSD 유효성 검사기는 다음과 같이 당신에게 메시지를 제공합니다 :

Validation error on line 12 column 17 of books.xml: 
    FORG0001: In content of element <ITEM>: The content model does not allow element <PRICE> 
    to appear immediately after element <PUB-DATE>. It must be preceded by <LANGUAGE>. 
    See http://www.w3.org/TR/xmlschema-1/#cvc-complex-type clause 2.4 

당신은 패턴과 일치하는 오류 메시지와 누락 된 요소의 이름을 추출을 시도 할 수 있습니다.

대부분의 스키마 프로세서가이 정보를 제공하지 않는 이유는 내부적으로 작업하는 방식 때문입니다. 일반적으로 스키마 프로세서는 입력의 각 요소에 대해 어떤 요소가 다음에 올지를 나타내는 유한 상태 시스템을 구성합니다. 다음 요소가 허용되지 않는 요소라면 FSM에서 왜 이것이이 경우인지 즉시 알 수 없습니다. Saxon은 진단을 개선하고 개선하기 위해 몇 가지 추가 분석을 수행합니다. 입력에 A에서 C 로의 허용되지 않는 전환이 포함되어있는 경우 FSM을 검색하여 A에서 B 및 B에서 C로 허용되는 전환이 있음을 발견하고 오류를 만듭니다 B가 누락되었다고 말하는 메시지.

+0

확실히 패턴 매칭을 구현할 수 있습니다. 하지만 뭔가 구체적인 것을 찾고 있어요. 오류가 발생하여 이벤트를 통해 캡처 할 수있는 코드의 일부를 찾고 있는데, 이전 형제를 찾을 수 있습니다. ** StAX가 앞으로 만 전달되므로 DOM이 원인을 제공 할 수 있습니까? – mark42inbound

+0

SAXParseException의 메시지는 다음과 같습니다. ** cvc-complex-type.2.4.a : 'PHSHumanSubjectsAndClinicalTrialsInfo : HumanSubjectsIndicator1'요소로 시작하는 잘못된 콘텐츠가 발견되었습니다. '{ "http://apply.grants.gov/forms/PHSHumanSubjectsAndClinicalTrialsInfo-V1.0"HumanSubjectsIndicator}"중 하나가 필요합니다. **이 메시지는 내부적으로 형성 될 수 있으므로 요소 이름을 추출하는 방법이 있습니까? 몇 가지 구체적인 방법? – mark42inbound

+0

메시지는 'HumanSubjectsIndicato r1' 대신에 다른 것이 있어야 함을 의미합니다. 그리고 그 중 하나는 "그 중 하나"다음에 그 목록에 있습니다.또한 XSD를 검사하여'HumanSubjectsIndicato r1' 대신에 무엇이 있어야하는지 더 잘 이해할 수 있습니다. – Vadim