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

查看:120
本文介绍了使用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.

任何输入赞赏!

推荐答案

在理想的世界中,您可以使用 Validator 。这样的事情:

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的模式实例。您可以跟踪第三方实现。

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天全站免登陆