2017-12-07 3 views
0

は、XSD以下のJava/Groovyの:以下は行番号でXMLノードを検索

import java.io.File; 
import java.io.IOException; 

import javax.xml.XMLConstants; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 
import javax.xml.validation.Validator; 
import javax.xml.transform.sax.SAXSource 
import javax.xml.parsers.SAXParserFactory 
import org.xml.sax.SAXException 
import org.xml.sax.InputSource 
import org.xml.sax.SAXParseException 
import org.xml.sax.ErrorHandler 


def validateXMLSchema(String xsdPath, String xmlPath) { 
    final List <SAXParseException> exceptions = new LinkedList <SAXParseException>(); 
    try { 
     SchemaFactory factory = 
     SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema = factory.newSchema(new File(xsdPath)); 
     Validator validator = schema.newValidator(); 
     validator.setErrorHandler(new ErrorHandler() { 
     @Override 
     public void warning(SAXParseException exception) throws SAXException { 
     exceptions.add(exception); 
     } 

     @Override 
     public void fatalError(SAXParseException exception) throws SAXException { 
     exceptions.add(exception); 
     } 

     @Override 
     public void error(SAXParseException exception) throws SAXException { 
     exceptions.add(exception); 
     } 
     }); 
     def xmlFile = new File(xmlPath); 
     validator.validate(new StreamSource(xmlFile)); 
     exceptions.each { 
     println 'lineNumber : ' + it.lineNumber + '; message : ' + it.message 
     } 
    } catch (IOException | SAXException e) { 
     println("Exception: line ${e.lineNumber} " + e.getMessage()); 
     return false; 
    } 
    return exceptions.size() == 0; 
} 

aginst XMLスキーマを検証するために私のGroovyコードで検証エラーの一部です、私はメッセージごとに行番号にアクセスすることができますし、

対応するノード名を見つけようとしています
lineNumber : 106; message : cvc-datatype-valid.1.2.1: '' is not a valid value for 'date'. 
lineNumber : 248; message : cvc-enumeration-valid: Value 'Associate' is not facet-valid with respect to enumeration '[ADJSTR, ADJSMT] 

行番号をusinngエラーメッセージをcorresponsdingためのノード名を見つけるための簡単な方法はありますか?または、その特定の行を読んで、XmlSlurperを使って以下のように解析する必要があります(このアプローチを避けようとすると、ユーザ負荷の高いより大きいXMLファイルの方が遅くなります)。

def getNodeName(xmlFile, lineNumber){ 
    def xmlLine = xmlFile.readLines().get(lineNumber) 
    def node = new XmlSlurper().parseText(xmlLine.toString()) 
    node.name() 
} 
+0

xmlを開いてこれらの推奨事項を変更する必要があります。 – Rao

+0

[Java 8/Groovy:XSDでXMLを検証し、例外または検証エラーのノードを見つける](https://stackoverflow.com/questions/47682190/java-8-groovy-validate-xml-with)の可能な複製-an-xsd-and-an-except-for-an-an-exception-or-aa) – cfrick

答えて

1

これはエレガントではありませんが、以下のgetNodeName()は(full example here)速くする必要があります:

def getNodeName(xmlFile, lineNumber) { 
    def result = "unknown" 
    def count = 1 
    def NODE_REGEX = /.*?<(.*?)>.*/ 
    def br 

    try { 
     br = new BufferedReader(new FileReader(xmlFile)) 
     String line 
     def isDone = false 
     while ((! isDone) && (line = br.readLine()) != null) { 
      if (count == lineNumber) { 
       def matcher = (line =~ NODE_REGEX) 
       if (matcher.matches()) { 
        result = matcher[0][1] 
       } 
       isDone = true 
      } 
      count++ 
     } 
    } finally { 
     // TODO: better exception handling 
     br.close() 
    } 

    return result 
} 

それは単に問題の行までの行を読み取り、名前を取得するには初歩的な正規表現を使用しています。あなたが好むならあなたの例のように潜在的にXmlSlurperを使用することができます。重要なことは、ファイルIO /メモリがかなり少なくなることです。