Java 如何允许正确验证不同的XSD版本?

Java 如何允许正确验证不同的XSD版本?,java,xml,sax,xml-validation,Java,Xml,Sax,Xml Validation,我试图更新一些xml解析器,但遇到了一个小问题。我们有一个xsd,需要与旧版本的xml保持兼容,我们必须对它进行一些更改。我们在新版本的xsd中进行了更改,我们希望使用相同的解析器(因为更改通常非常小,解析器可以轻松地处理这两个问题)。我们正在使用XMLReader属性”http://java.sun.com/xml/jaxp/properties/schemaSource“使用以下方法将架构设置为上一版本: xmlReader.setProperty("http://java.sun.com/

我试图更新一些xml解析器,但遇到了一个小问题。我们有一个xsd,需要与旧版本的xml保持兼容,我们必须对它进行一些更改。我们在新版本的xsd中进行了更改,我们希望使用相同的解析器(因为更改通常非常小,解析器可以轻松地处理这两个问题)。我们正在使用
XMLReader
属性
”http://java.sun.com/xml/jaxp/properties/schemaSource“
使用以下方法将架构设置为上一版本:

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.0"
    xmlns="http://www.mycompany.com/my-xsd-1.0"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">
List<InputSource> inputs = new ArrayList<InputSource>();
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.1.xsd")));

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    inputs.toArray(new InputSource[inputs.size()]));
当我们只有一个版本的模式时,这种方法工作得很好。现在我们有了一个新版本,我们希望系统使用传入xml中定义的模式的任何版本。两种模式都定义了一个名称空间,类似于以下内容:

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.0"
    xmlns="http://www.mycompany.com/my-xsd-1.0"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">
List<InputSource> inputs = new ArrayList<InputSource>();
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.1.xsd")));

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    inputs.toArray(new InputSource[inputs.size()]));

对于新的一个:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.1"
    xmlns="http://www.mycompany.com/my-xsd-1.1"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">

因此,它们定义了不同的名称空间和不同的模式“位置”。我们不希望模式存在于“网络”上——我们希望它与我们的系统捆绑在一起。有没有一种方法可以使用setProperty机制来执行此行为,或者有其他方法来处理此行为


我尝试将这两个资源作为参数放在数组的输入流中,但没有成功(我记得在某个地方读到过,这是一个可能的解决方案-尽管现在我找不到源,所以这可能是一厢情愿的想法)。

我个人认为,在版本架构时更改名称空间通常是个坏主意,除非这些改变是激进的,但在这一点上观点不同,而且你似乎已经做出了决定,你也可以从中获益

由于您使用的是两个不同的名称空间,模式可能是不相交的,因此您应该能够为处理器提供一个模式,它是两个名称空间的并集-我不知道是否有更好的方法,但实现这一点的一种方法是编写一个小存根模式,将两者都导入,并将此存根作为schemaSource属性提供。处理器将使用与源文档中元素的名称空间匹配的模式声明


(使用特定于版本的名称空间使这项任务-验证-更容易。但它使XML的后续处理(例如使用XPath)更难,因为很难编写同时使用这两个名称空间的代码。)

因此,事实证明,我尝试过的方法实际上是有效的-我们意外地使用了无效的XML!(对其他感兴趣的人)有效的方法如下:

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.mycompany.com/my-xsd-1.0"
    xmlns="http://www.mycompany.com/my-xsd-1.0"
    elementFormDefault="unqualified" attributeFormDefault="unqualified">
List<InputSource> inputs = new ArrayList<InputSource>();
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.0.xsd")));
inputs.add(new InputSource(getClass().getResourceAsStream("/schema/my-xsd-1.1.xsd")));

xmlReader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", 
    inputs.toArray(new InputSource[inputs.size()]));
List inputs=new ArrayList();
add(新的InputSource(getClass().getResourceAsStream(“/schema/my-xsd-1.0.xsd”));
add(新的InputSource(getClass().getResourceAsStream(“/schema/my-xsd-1.1.xsd”));
xmlReader.setProperty(“http://java.sun.com/xml/jaxp/properties/schemaSource", 
inputs.toArray(新的InputSource[inputs.size()]);

因此,与其更改名称空间,不如建议保留相同的名称空间,只更改版本号?那么,您将如何将正确的版本传递给验证器呢?我也应该澄清一下——我不反对您更改名称空间——我继承了这一点。我可以更改它,这样名称空间就不会更改,我只想弄清楚如何适当地处理不同XSD的查找。