Как получить номер строки ошибки при проверке XML файла по схеме XML

Я пытаюсь проверять XML на XML-схему W3C.

Следующий код выполняет задание и отчеты при возникновении ошибки. Но я не могу получить номер строки ошибки. Он всегда возвращает -1.

Есть ли простой способ получить номер строки?

import java.io.File;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.xml.sax.SAXParseException;

    public class XMLValidation {

        public static void main(String[] args) {

            try {
                DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                Document document = parser.parse(new File("myxml.xml"));

                SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                Source schemaFile = new StreamSource(new File("myschema.xsd"));

                Schema schema = factory.newSchema(schemaFile);

                Validator validator = schema.newValidator();

                validator.validate(new DOMSource(document));

            } catch (SAXParseException e) {
                System.out.println(e.getLineNumber());
                e.printStackTrace();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Ответы

Ответ 1

Я нашел это

http://www.herongyang.com/XML-Schema/Xerces2-XSD-Validation-with-XMLReader.html

который, как представляется, предоставляет следующие сведения (для включения номеров строк)

Error:
   Public ID: null
   System ID: file:///D:/herong/dictionary_invalid_xsd.xml
   Line number: 7
   Column number: 22
   Message: cvc-datatype-valid.1.2.1: 'yes' is not a valid 'boolean' 
   value.

используя этот код:

/**
 * XMLReaderValidator.java
 * Copyright (c) 2002 by Dr. Herong Yang. All rights reserved.
 */
import java.io.IOException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
class XMLReaderValidator {
   public static void main(String[] args) {
      String parserClass = "org.apache.xerces.parsers.SAXParser";
      String validationFeature 
         = "http://xml.org/sax/features/validation";
      String schemaFeature 
         = "http://apache.org/xml/features/validation/schema";
      try {
         String x = args[0];
         XMLReader r = XMLReaderFactory.createXMLReader(parserClass);
         r.setFeature(validationFeature,true);
         r.setFeature(schemaFeature,true);
         r.setErrorHandler(new MyErrorHandler());
         r.parse(x);
      } catch (SAXException e) {
         System.out.println(e.toString()); 
      } catch (IOException e) {
         System.out.println(e.toString()); 
      }
   }
   private static class MyErrorHandler extends DefaultHandler {
      public void warning(SAXParseException e) throws SAXException {
         System.out.println("Warning: "); 
         printInfo(e);
      }
      public void error(SAXParseException e) throws SAXException {
         System.out.println("Error: "); 
         printInfo(e);
      }
      public void fatalError(SAXParseException e) throws SAXException {
         System.out.println("Fattal error: "); 
         printInfo(e);
      }
      private void printInfo(SAXParseException e) {
         System.out.println("   Public ID: "+e.getPublicId());
         System.out.println("   System ID: "+e.getSystemId());
         System.out.println("   Line number: "+e.getLineNumber());
         System.out.println("   Column number: "+e.getColumnNumber());
         System.out.println("   Message: "+e.getMessage());
      }
   }
}

Ответ 2

Попробуйте использовать SAXLocator http://download.oracle.com/javase/1.5.0/docs/api/org/xml/sax/Locator.html Парсерам не требуется их подавать, но если они это делают, они должны сообщать номера строк

Я думаю, что ваш код должен включать:

 // this will be called when XML-parser starts reading
    // XML-data; here we save reference to current position in XML:
    public void setDocumentLocator(Locator locator) {
        this.locator = locator;
    }

(см. http://www.java-tips.org/java-se-tips/org.xml.sax/using-xml-locator-to-indicate-current-parser-pos.html)

Анализатор предоставит вам локатор, который затем можно использовать для получения номера строки. Возможно, стоит распечатать/отладить, когда это произойдет, чтобы увидеть, есть ли у вас действующий локатор

Ответ 3

Вы можете просто поймать SaxException e. Затем вызовите e.toString()

Это даст что-то вроде:

org.xml.sax.SAXParseException; lineNumber: 2668151; columnNumber: 80; Последовательность символов "]] > " не должна отображаться в содержимом, если не используется для обозначения конца раздела CDATA.