Проверьте файл XML по локальному файлу DTD с помощью Java.

Как я могу проверить файл XML по DTD, который хранится локально как файл? Файл XML не имеет никакого объявления DOCTYPE (или может иметь такое, которое затем должно быть переопределено). Я посмотрел наэта тема но помимо того, что они используют .NET, я сомневаюсь, что это хорошее решение.

Любой вклад приветствуется!

Ответы на вопрос(3)

Решение Вопроса

Validator, Что-то вроде этого:

SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.XML_DTD_NS_URI);
Schema schema = schemaFactory.newSchema(new File(
    "xmlValidate.dtd"));
Validator validator = schema.newValidator();
validator.validate(new StreamSource("xmlValidate.xml"));

К сожалению, реализация Sun (по крайней мере, в Java 6) не включает поддержку создания экземпляра схемы из DTD. Возможно, вы сможете отследить стороннюю реализацию.

Лучше всего изменить документ, включив в него DTD, перед анализом, используя другой механизм.

Вы можете использоватьтрансформатор чтобы вставить объявление DTD:

TransformerFactory tf = TransformerFactory
    .newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(
    OutputKeys.DOCTYPE_SYSTEM, "xmlValidate.dtd");
transformer.transform(new StreamSource(
    "xmlValidate.xml"), new StreamResult(System.out));

... но это, похоже, не заменяет существующую декларацию DTD.

этоStAX читатель событий может сделать работу:

  public static class DTDReplacer extends
      EventReaderDelegate {

    private final XMLEvent dtd;
    private boolean sendDtd = false;

    public DTDReplacer(XMLEventReader reader, XMLEvent dtd) {
      super(reader);
      if (dtd.getEventType() != XMLEvent.DTD) {
        throw new IllegalArgumentException("" + dtd);
      }
      this.dtd = dtd;
    }

    @Override
    public XMLEvent nextEvent() throws XMLStreamException {
      if (sendDtd) {
        sendDtd = false;
        return dtd;
      }
      XMLEvent evt = super.nextEvent();
      if (evt.getEventType() == XMLEvent.START_DOCUMENT) {
        sendDtd = true;
      } else if (evt.getEventType() == XMLEvent.DTD) {
        // discard old DTD
        return super.nextEvent();
      }
      return evt;
    }

  }

Он отправит данную декларацию DTD сразу после запуска документа и откажется от любого из старого документа.

Использование демо:

XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent dtd = eventFactory
    .createDTD("<!DOCTYPE Employee SYSTEM \"xmlValidate.dtd\">");

XMLInputFactory inFactory = XMLInputFactory.newInstance();
XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
XMLEventReader reader = inFactory
    .createXMLEventReader(new StreamSource(
        "xmlValidate.xml"));
reader = new DTDReplacer(reader, dtd);
XMLEventWriter writer = outFactory.createXMLEventWriter(System.out);
writer.add(reader);
writer.flush();

// TODO error and proper stream handling

Обратите внимание, что XMLEventReader может формировать источник для некоторого другого механизма преобразования, который выполнял проверку.

Было бы намного проще проверить с использованием схемы W3, если у вас есть такая опция.

 12 нояб. 2011 г., 12:52
мой файл XML не имеет никакого объявления DOCTYPE. и я разбираю файл, используя SAXParser в Android. DTD генерируется мной. Как я могу проверить файл XML, используя мой DTD, в разборе SAX?
 15 нояб. 2011 г., 04:54
Я уже спрашивалquestion но я не получил правильный ответ.
 19 нояб. 2016 г., 22:55
WstxParsingException / FileNotFoundException генерируется, если отброшенный системный идентификатор DTD ссылается на файл, который не существует. добавлятьinFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false) после заводской реализации.
 Simon09 июл. 2009 г., 01:20
Большое спасибо за ваш исчерпывающий ответ, который мне очень помогает. Я посмотрю на преобразование DTD в схему W3, так как тогда я смогу использовать Валидатор Солнца.
 12 нояб. 2011 г., 18:11
@ Khushbu - было бы лучше, если бы вы задали новый вопрос.

Thanks for your help, but what if no DOCTYPE has been specified at all? The EntityResolver would not help me in that case, would it? – Simon Jul 8 '09 at 6:34

@Bluegene: What are you validating against if no DOCTYPE? – J-16 SDiZ Jul 8 '09 at 7:12

Against my own DTD. I just want to make sure the XML I receive conforms to my DTD, not just any DTD the sender specifies. – Simon Jul 8 '09 at 23:09

если проблема заключается в том, что вы хотите, чтобы он был проверен на соответствие вашему dtd, а не авторам, вы должны убедиться, что имеется четкая документация, в которой подробно описан тип документа и что должно быть в файле xml.

EntityResolver, проверять, выписыватьсяэтот пример.

 Simon09 июл. 2009 г., 01:09
Против моего собственного DTD. Я просто хочу убедиться, что получаемый XML соответствуетmy DTD, а не просто DTD, указанный отправителем.
 08 июл. 2009 г., 09:12
@Bluegene: Что вы проверяете, если нет DOCTYPE?
 Simon08 июл. 2009 г., 08:34
Спасибо за вашу помощь, но что, если DOCTYPE не был указан вообще? EntityResolver не поможет мне в этом случае, не так ли?

Ваш ответ на вопрос