使用 Java 根据本地 DTD 文件验证 XML 文件 [英] Validate an XML file against local DTD file with Java

查看:36
本文介绍了使用 Java 根据本地 DTD 文件验证 XML 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何根据本地存储为文件的 DTD 验证 XML 文件?XML 文件没有任何 DOCTYPE 声明(或者可能有一个应该被覆盖的声明).我看了这个线程 但除了他们使用 .NET 的事实之外,我怀疑这是一个很好的解决方案.

How can I validate an XML file against a DTD that is stored locally as a file? The XML file does not have any DOCTYPE declaration (or may have one that should then be overridden). I had a look at this thread but besides the fact they are using .NET I doubt that this is a good solution.

感谢任何输入!

推荐答案

在理想的世界中,您将能够使用 验证器.像这样:

In an ideal world, you'd be able to validate using a Validator. Something like this:

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 创建 Schema 实例.您或许可以追踪第 3 方实施.

Unfortunately, the Sun implementation (at least, as of Java 6) does not include support for creating a Schema instance from a DTD. You might be able to track down a 3rd party implementation.

最好的办法是在使用其他机制解析之前修改文档以包含 DTD.

Your best bet may be to alter the document to include the DTD before parsing using some other mechanism.

您可以使用转换器 插入 DTD 声明:

You can use a transformer to insert a DTD declaration:

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 声明.

...but this does not seem to replace an existing DTD declaration.

这个 StAX事件阅读器可以完成这项工作:

This StAX event reader can do the job:

  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 声明并丢弃旧文档中的任何声明.

It will send a given DTD declaration right after the document start and discard any from the old document.

演示用法:

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 可以构成执行验证的其他一些转换机制的源.

Note that the XMLEventReader could form the source for some other transformation mechanism that performed validation.

如果您有该选项,使用 W3 架构进行验证会容易得多.

It would be much easier to validate using a W3 schema if you have that option.

这篇关于使用 Java 根据本地 DTD 文件验证 XML 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆