Вопрос по dtd, java, validation, xml – Проверьте файл XML по локальному файлу DTD с помощью Java.

23

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

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

Ваш Ответ

3   ответа
25

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, если у вас есть такая опция.

мой файл XML не имеет никакого объявления DOCTYPE. и я разбираю файл, используя SAXParser в Android. DTD генерируется мной. Как я могу проверить файл XML, используя мой DTD, в разборе SAX?
Я уже спрашивалquestion но я не получил правильный ответ.
WstxParsingException / FileNotFoundException генерируется, если отброшенный системный идентификатор DTD ссылается на файл, который не существует. добавлятьinFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false) после заводской реализации.
Большое спасибо за ваш исчерпывающий ответ, который мне очень помогает. Я посмотрю на преобразование DTD в схему W3, так как тогда я смогу использовать Валидатор Солнца. Simon
@ Khushbu - было бы лучше, если бы вы задали новый вопрос.
3

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.

1

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

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

Похожие вопросы