我有一个简单的XML文件和一个表示它的简单DTD。
我正在使用可能 可行,虽然可能不适合使用DTD验证标记(而不是实际架构,我相信是最强大和最合适的选择)。
基于此假设,我想我会尝试使用StaX。
问题
即使提供了有效的DTD,StaX似乎也没有验证任何内容,并且XML文件与DTD中定义的模式不匹配。
我希望下面的代码能够通过一些与验证相关的堆栈跟踪失败,而不是打印我的 foo.xml 文件中的所有元素名称。
我认为我的假设可能存在一些非常错误,但在我浏览的相关SO问题中,以及其他在线文献中都找不到任何具体的解释。
以下代码和资源。
foo.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT foo (bar+) >
<!ATTLIST foo
foo CDATA #REQUIRED
>
<!ELEMENT bar (#PCDATA) >
<!ATTLIST bar
bar (bar|blah) #REQUIRED
>
foo.xml
<?xml version="1.0" encoding="UTF-8"?>
<foo foo="foo">
<!-- attribute "blah" invalid -->
<bar bar="bar" blah="blah">bar</bar>
<!-- invalid -->
<bar />
</foo>
码
XMLInputFactory xif = XMLInputFactory.newFactory();
// not sure if this is required? doens't seem to help
xif.setProperty(XMLInputFactory.IS_VALIDATING, "true");
// adding dtd
xif.setXMLResolver(
new XMLResolver() {
public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace) throws XMLStreamException {
if ("foo.dtd".equals(systemID)) {
return Main.class.getResourceAsStream("foo.dtd");
}
else {
return null;
}
};
}
);
XMLStreamReader reader = null;
try {
reader = xif.createXMLStreamReader(Main.class.getResourceAsStream("foo.xml"));
while (reader.hasNext()) {
switch (reader.next()) {
// prints local name just for testing
// - expecting this to fail at some point
case XMLStreamReader.START_ELEMENT:
System.out.println(reader.getLocalName());
}
}
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (Exception e) {}
}
}
输出(期待一些堆栈跟踪)
foo
bar
bar
答案 0 :(得分:1)
我可以看到的第一个问题是您正在测试systemID("foo.dtd".equals(systemID)
),但您的XML文件没有指向DTD的系统标识符。
尝试将带有系统标识符的doctype声明添加到XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo SYSTEM "foo.dtd">
<foo foo="foo">
<!-- attribute "blah" invalid -->
<bar bar="bar" blah="blah">bar</bar>
<!-- invalid -->
<bar />
</foo>
此外,according to this question,您将需要使用不同的StAX实现,因为默认情况下不支持验证。
与该问题的答案中建议的一样,我尝试使用woodstox将woodstox 5.0.3 jar和stax2 api 4.0.0 jar添加到我的类路径中(并将带有系统标识符的doctype添加到XML中)并得到了预期的例外:
foo
Nov 28, 2016 3:09:53 PM so.test2.SOTest2 main
SEVERE: null
com.ctc.wstx.exc.WstxValidationException: Element <bar> has no attribute "blah"
at [row,col {unknown-source}]: [5,5]
at com.ctc.wstx.exc.WstxValidationException.create(WstxValidationException.java:50)
at com.ctc.wstx.sr.StreamScanner.reportValidationProblem(StreamScanner.java:580)
at com.ctc.wstx.sr.ValidatingStreamReader.reportValidationProblem(ValidatingStreamReader.java:383)
at com.ctc.wstx.sr.InputElementStack.reportProblem(InputElementStack.java:849)
at com.ctc.wstx.dtd.DTDValidatorBase.doReportValidationProblem(DTDValidatorBase.java:497)
at com.ctc.wstx.dtd.DTDValidatorBase.reportValidationProblem(DTDValidatorBase.java:479)
at com.ctc.wstx.dtd.DTDValidator.validateAttribute(DTDValidator.java:251)
at com.ctc.wstx.sr.AttributeCollector.validateAttribute(AttributeCollector.java:729)
at com.ctc.wstx.sr.InputElementStack.resolveAndValidateElement(InputElementStack.java:535)
at com.ctc.wstx.sr.BasicStreamReader.handleStartElem(BasicStreamReader.java:3059)
at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2919)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1123)
at so.test2.SOTest2.main(SOTest2.java:56)