Разница в DocumentBuilder.parse при использовании JRE 1.5 и JDK 1.6 - PullRequest
6 голосов
/ 12 марта 2010

Недавно мы наконец-то переключили наши проекты на Java 1.6. При выполнении тестов я обнаружил, что при использовании 1.6 не генерируется SAXParseException, который был сгенерирован с использованием 1.5.

Ниже приведен мой тестовый код для демонстрации проблемы.

<code>import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;

import org.junit.Test;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;


/**
 * Test class to demonstrate the difference between JDK 1.5 to JDK 1.6.
 * 
 * Seen on Linux:
 * 
 * <pre>
 * #java version "1.6.0_18"
 * Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
 * Java HotSpot(TM) Server VM (build 16.0-b13, mixed mode)
 * 
* * При просмотре в OSX: * *
 * java version "1.6.0_17"
 * Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025)
 * Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
 * 
* * @author dhiller (создатель) * @author $ Author $ (последний редактор) * @version $ Revision $ * @ since 12.03.2010 11:32:31 * / открытый класс TestXMLValidation { / ** * Проверяет проверку схемы XML на простую схему. * * Исключения @throws * Водопад Эйн Фелер Ауфтритт * @throws junit.framework.AssertionFailedError * Falls eine Unit-Test-Pruefung fehlschlaegt * / @Test (ожидается = SAXParseException.class) public void testValidate () создает исключение { окончательная схема StreamSource = новый StreamSource (новый StringReader ("<? xml version = \" 1.0 \ "encoding = \" UTF-8 \ "?>" + "" + "" + "</ xs: schema>")); final String xml = ""; final DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance (); newFactory.setSchema (SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema") .newSchema (схема)); final DocumentBuilder documentBuilder = newFactory.newDocumentBuilder (); documentBuilder.parse (новый InputSource (новый StringReader (xml))); } }

При использовании JVM 1.5 тест проходит успешно, на 1.6 он завершается с «Ожидаемым исключением SAXParseException».

Javadoc DocumentBuilderFactory.setSchema (схема) Метод говорит:

При обнаружении ошибок валидатор, парсер отвечает сообщить о них указанному пользователем ErrorHandler (или если обработчик ошибок не установлено, игнорировать их или бросить их), как и любые другие ошибки найден самим парсером. В других слова, если пользователь указал ErrorHandler установлен, он должен получить эти ошибки, и если нет, то они должны быть обрабатываются в соответствии с ошибка по умолчанию для конкретной реализации правила обработки.

Javadoc метода DocumentBuilder.parse (InputSource) говорит:

Кстати: я пытался установить обработчик ошибок с помощью setErrorHandler , но все еще не исключение

Теперь мой вопрос:

Что изменилось в 1.6, что препятствует проверке схемы для выдачи SAXParseException? Это связано со схемой или с XML, который я пытался проанализировать?

Обновление:

Следующий код работает на 1.5 и 1.6, как я и хотел:

  @Test(expected = SAXParseException.class)
  public void testValidate() throws Exception {
    final StreamSource schema = new StreamSource( new StringReader( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
      + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" "
      + "elementFormDefault=\"qualified\" xmlns:xsd=\"undefined\">" + "<xs:element name=\"Test\"/>" + "</xs:schema>" ) );
    final String xml = "<Test42/>";
    final DocumentBuilderFactory newFactory = DocumentBuilderFactory.newInstance();
    final Schema newSchema = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" ).newSchema( schema );
    newFactory.setSchema( newSchema );
    final Validator newValidator = newSchema.newValidator();
    final Source is = new StreamSource( new StringReader( xml ) );
    try {
      newValidator.validate( ( Source ) is );
    }
    catch ( Exception e ) {
      e.printStackTrace();
      throw e;
    }
    final DocumentBuilder documentBuilder = newFactory.newDocumentBuilder();
    documentBuilder.parse( new InputSource( new StringReader( xml ) ) );
  }

Решение, по-видимому, заключается в явном использовании экземпляра Validator, созданного из экземпляра схемы. Я нашел решение здесь

Тем не менее, я не уверен, почему это ...

1 Ответ

1 голос
/ 01 июня 2011

Очевидно, что документ, не соответствующий схеме, заслуживает лишь мягкого упрека в stderr из обработчика ошибок по умолчанию.Мое решение состояло в том, чтобы заменить обработчик ошибок по умолчанию более строгим:

// builder is my DocumentBuilder
builder.setErrorHandler(new ErrorHandler() {
    @Override
    public void error(SAXParseException arg0) throws SAXException {
        throw arg0;             
    }

    @Override
    public void fatalError(SAXParseException arg0) throws SAXException {
        throw arg0;                 
    }

    @Override
    public void warning(SAXParseException arg0) throws SAXException {
        throw arg0;                 
    }
});
...