【发布时间】:2014-12-19 03:58:35
【问题描述】:
Java 8. Eclipse Luna。我在分配由匿名方法主体访问的最终变量时遇到了奇怪的麻烦。
背景
我正在使用我自己选择的 XSD 架构来验证无命名空间的 XML 文件。该文件没有xmlns 声明,但架构有targetNamespace="mynamespace" 声明。显然,该文件将无法通过验证。为了让它无论如何都通过验证,我给验证器一个过滤器来强制它假装XML文件有xmlns="mynamespace",正如here所建议的那样。请参阅下面的代码。
问题
注意变量targetNamespace。如果我使用字符串文字命名空间对其进行初始化,则验证通过。如果我使用返回相同值的方法调用进行初始化,验证将失败。
守则
public static void validate(byte[] xmlFile, byte[] xsdFile)
throws SAXException, IOException, XMLStreamException, FactoryConfigurationError {
final String targetNamespace = "mynamespace"; // PASS!
//final String targetNamespace = getTargetNamespace(xsdFile); // FAIL!
XMLFilter namespaceFilter = new XMLFilterImpl(XMLReaderFactory.createXMLReader()) {
@Override
public void startElement(String uri, String localName, String qName, Attributes atts)
throws SAXException {
// Make the validator think the XML file's elements have a namespace
uri = targetNamespace;
super.startElement(uri, localName, qName, atts);
}
};
Source xmlSource = new SAXSource(namespaceFilter, new InputSource(new ByteArrayInputStream(xmlFile)));
Source xsdSource = new StreamSource(new ByteArrayInputStream(xsdFile));
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(xsdSource).newValidator().validate(xmlSource);
}
private static String getTargetNamespace(byte[] xsdFile)
throws XMLStreamException, FactoryConfigurationError {
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new ByteArrayInputStream(xsdFile));
while (reader.hasNext()) {
int event = reader.next();
// Get the root element's "targetNamespace" attribute
if (event == XMLEvent.START_ELEMENT) {
return reader.getAttributeValue(null, "targetNamespace");
}
}
return null;
}
错误
cvc-complex-type.2.4.a:发现以元素“childtag”开头的无效内容。需要 '{"mynamespace":childtag}' 之一。
它变得更加离奇。当方法以字符串文字形式返回 "mynamespace" 时,验证通过。但是当该方法从 XSD 文件中获取 "mynamespace" 的值时,验证失败。我已通过String.equals() 验证,验证失败时传递给super.startElement 的值确实与验证通过时完全相同!
我在这里看到的唯一区别是,当分配给最终变量 targetNamespace 的值最终是 一个常量(字符串文字)时它通过,并且当分配的值是最终由某些条件确定(源自 XSD 文件)。最终或有效最终没有区别。
这是一个已知的 Java 错误吗?还是我对从匿名方法访问的变量的初始化缺乏了解? XSD验证真的和它有关系吗?
【问题讨论】:
-
我发现了问题!这是一个Java错误。 XSD 代码的 JDK 开发人员在此方法中使用 == 而不是 String.equals() 将 XML 标记“childtag”与预期的 XSD“childtag”进行了比较:com.sun.org.apache.xerces.internal.impl。 xs.SubstitutionGroupHandler.getMatchingElemDecl(QName, XSElementDecl) 现在报告错误并找到解决方法...
标签: java xml validation xsd