使用 Java 根据本地 DTD 文件验证 XML 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1096365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validate an XML file against local DTD file with Java
提问by Simon
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 threadbut besides the fact they are using .NET I doubt that this is a good solution.
如何根据本地存储为文件的 DTD 验证 XML 文件?XML 文件没有任何 DOCTYPE 声明(或者可能有一个应该被覆盖的声明)。我看过这个线程,但除了他们使用 .NET 的事实之外,我怀疑这是一个很好的解决方案。
Any input appreciated!
任何输入表示赞赏!
采纳答案by McDowell
In an ideal world, you'd be able to validate using a Validator. Something like this:
在理想情况下,您可以使用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"));
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.
不幸的是,Sun 实现(至少从 Java 6 开始)不支持从 DTD 创建 Schema 实例。您也许能够追踪第 3 方实施。
Your best bet may be to alter the document to include the DTD before parsing using some other mechanism.
最好的办法可能是在使用其他机制解析之前修改文档以包含 DTD。
You can use a transformerto insert a DTD declaration:
您可以使用转换器插入 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));
...but this does not seem to replace an existing DTD declaration.
...但这似乎并没有取代现有的 DTD 声明。
This StAXevent reader can do the job:
这个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;
}
}
It will send a given DTD declaration right after the document start and discard any from the old document.
它将在文档开始后立即发送给定的 DTD 声明并丢弃旧文档中的任何声明。
Demo usage:
演示用法:
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
Note that the XMLEventReader could form the source for some other transformation mechanism that performed validation.
请注意, XMLEventReader 可以形成执行验证的某些其他转换机制的源。
It would be much easier to validate using a W3 schema if you have that option.
如果您有该选项,则使用 W3 模式进行验证会容易得多。
回答by J-16 SDiZ
You have to implement the EntityResolver
, checkout this example.
你必须实现EntityResolver
,结帐这个例子。
回答by zachary
im pretty sure the stuff aforementioned will work..
我很确定前面提到的东西会起作用..
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
感谢您的帮助,但是如果根本没有指定 DOCTYPE 呢?在这种情况下,EntityResolver 不会帮助我,是吗?– 西蒙 2009 年 7 月 8 日 6:34
@Bluegene:如果没有 DOCTYPE,你要验证什么?– J-16 SDiZ 09 年 7 月 8 日 7:12
反对我自己的 DTD。我只想确保我收到的 XML 符合我的 DTD,而不仅仅是发件人指定的任何 DTD。– 西蒙 09 年 7 月 8 日,23:09
if the problem is you want it to be validated against your dtd rather than the authors you should ensure that there is clear documentation that details the doctype, and what must be in the xml file
如果问题是您希望根据您的 dtd 而不是作者对其进行验证,您应该确保有明确的文档详细说明 doctype,以及 xml 文件中必须包含的内容