在 Java 中:根据位于不同服务器位置的多个模式验证 XML

发布于 2024-09-14 11:26:19 字数 3095 浏览 5 评论 0原文

在我的程序中,我正在生成一个 XML 文件,并且需要根据位于不同 URL 上的多个架构来验证该 XML 文件。它需要一次性针对所有架构验证该 XML 文件。

源代码片段:

// here source array contain the locations of schemas, located at diff servers.
Source[] source = {
        new StreamSource(
                new URL("http://localhost:8081/test1/testSchema1.xsd")
                        .openStream()),
        new StreamSource(
                new URL(
                        "http://ccr.internal.ericsson.com/test2/testSchema2.xsd")
                        .openStream()) };

try {
    // Compile the schema, which loaded from schemaFileLocation.
    Schema schemaGrammar = schemaFactory.newSchema(source);

    // Create a validator for schema.
    Validator configValidator = schemaGrammar.newValidator();

    // set error handler with validator.
    SchemaValidator schemaValidator = new SchemaValidator();
    configValidator
            .setErrorHandler(schemaValidator.new MessageHandler());

    // validate xml instance against the grammar.
    configValidator.validate(new StreamSource(new File("xmlFile.xml")));
    System.out.println("\n");
} catch (SAXException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

当我运行上面的代码片段时,出现此错误:

org.xml.sax.SAXParseException: src-resolve:无法解析名称 'xn:SubNetwork' 到 a(n) ' 元素 声明'组件。在 org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(未知 来源)于 org.apache.xerces.util.ErrorHandlerWrapper.error(未知 来源)于 org.apache.xerces.impl.XMLErrorReporter.reportError(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDHandler.reportSchemaError(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDHandler.getGlobalDecl(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseSeqChoice(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseChoice(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.processComplexContent(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseComplexTypeDecl(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseLocal(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDHandler.traverseLocalElements(未知 来源)于 org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(未知 来源)于 org.apache.xerces.impl.xs.XMLSchemaLoader.loadSchema(未知 来源)于 org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(未知 来源)于 org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(未知 来源)于 org.apache.xerces.jaxp.validation.XMLSchemaFactory.newSchema(未知 来源)于 com.work.test.generateErrorLog(SchemaValidator.java:197)

代码中有什么问题?他们是否有其他方法来验证多个模式?

In my program, I am generating a XML file, and need to validate that XML file against multiple schemas which are located on different URLs. Its required to validate that XML file against all schema in onetime only.

Source fragment:

// here source array contain the locations of schemas, located at diff servers.
Source[] source = {
        new StreamSource(
                new URL("http://localhost:8081/test1/testSchema1.xsd")
                        .openStream()),
        new StreamSource(
                new URL(
                        "http://ccr.internal.ericsson.com/test2/testSchema2.xsd")
                        .openStream()) };

try {
    // Compile the schema, which loaded from schemaFileLocation.
    Schema schemaGrammar = schemaFactory.newSchema(source);

    // Create a validator for schema.
    Validator configValidator = schemaGrammar.newValidator();

    // set error handler with validator.
    SchemaValidator schemaValidator = new SchemaValidator();
    configValidator
            .setErrorHandler(schemaValidator.new MessageHandler());

    // validate xml instance against the grammar.
    configValidator.validate(new StreamSource(new File("xmlFile.xml")));
    System.out.println("\n");
} catch (SAXException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

When I run the above code fragment, I am get this error:

org.xml.sax.SAXParseException:
src-resolve: Cannot resolve the name
'xn:SubNetwork' to a(n) 'element
declaration' component. at
org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown
Source) at
org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown
Source) at
org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDHandler.reportSchemaError(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDHandler.getGlobalDecl(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseSeqChoice(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDAbstractParticleTraverser.traverseChoice(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.processComplexContent(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseComplexTypeDecl(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDComplexTypeTraverser.traverseLocal(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDElementTraverser.traverseLocal(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDHandler.traverseLocalElements(Unknown
Source) at
org.apache.xerces.impl.xs.traversers.XSDHandler.parseSchema(Unknown
Source) at
org.apache.xerces.impl.xs.XMLSchemaLoader.loadSchema(Unknown
Source) at
org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(Unknown
Source) at
org.apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar(Unknown
Source) at
org.apache.xerces.jaxp.validation.XMLSchemaFactory.newSchema(Unknown
Source) at
com.work.test.generateErrorLog(SchemaValidator.java:197)

What is the problem in code? Is their is any other way to validate against multiple schema?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吐个泡泡 2024-09-21 11:26:19

我也有同样的问题。

我改变了模式的顺序。

首先我导入了所有子架构,最后我设置了主架构。

Source[] sources = new Source[] { new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema1.xsd"), "UTF-8")), 
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema2.xsd"), "UTF-8")),
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema3.xsd"), "UTF-8")),
                              ...
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/mainschema.xsd"), "UTF-8"))};

I had the same problem.

I switched the order of the schemas.

First i imported all child schemas and at the end i set the main schema.

Source[] sources = new Source[] { new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema1.xsd"), "UTF-8")), 
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema2.xsd"), "UTF-8")),
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/subschema3.xsd"), "UTF-8")),
                              ...
                              new StreamSource(new InputStreamReader(SomeClass.class.getResourceAsStream("/com/foo/mainschema.xsd"), "UTF-8"))};
鸠魁 2024-09-21 11:26:19

关于这个主题的帖子很多,我也找不到令人满意的解决方案。这就是它对我的作用。为 SchemaFactory 提供自定义资源解析器


    Source source = new StreamSource(this.getClass().getResourceAsStream("ebics.xsd"));
    LSResourceResolver resolver = new ResourceResolver(schemaFactory.getResourceResolver());
    schemaFactory.setResourceResolver(resolver);
    

并仅解析顶级模式。然后解析器可以(希望)解析嵌入的引用


public class ResourceResolver implements LSResourceResolver {
    private LSResourceResolver parent = null;
    private Set returnedResources = new HashSet();


    public ResourceResolver(LSResourceResolver r){
    parent = r;
    }

    private ResourceResolver() {
    }

    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
    LSInput input = new LSInputImpl();

    if (returnedResources.contains(systemId)) {
        return null;
    } else if (systemId.equals("ebics_hev.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_hev.xsd"));
    } else if (systemId.equals("ebics_keymgmt_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_request.xsd"));
    } else if (systemId.equals("ebics_keymgmt_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_response.xsd"));
    } else if (systemId.equals("ebics_orders.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_orders.xsd"));
    } else if (systemId.equals("ebics_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_request.xsd"));
    } else if (systemId.equals("ebics_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_response.xsd"));
    } else if (systemId.equals("ebics_signature.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_signature.xsd"));
    } else if (systemId.equals("ebics_types.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_types.xsd"));
    } else if (systemId.equals("ebics.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics.xsd"));
    } else if (systemId.equals("xmldsig-core-schema.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("xmldsig-core-schema.xsd"));
    } else {
        return parent.resolveResource(type, namespaceURI, publicId, systemId, baseURI);
    }
    returnedResources.add(systemId);
    return input;
    }

}

这是 LSInputImpl


public class LSInputImpl implements LSInput
{

    public Reader getCharacterStream () {
        return null;
    }

    public void setCharacterStream ( Reader characterStream ) {}

    public InputStream getByteStream () {
        InputStream retval = null;
        if ( byteStream != null ) {
            retval = byteStream;
        }
        return retval;
    }

    public void setByteStream ( InputStream byteStream ) {
        this.byteStream = byteStream;
    }

    public String getStringData () {
        return null;
    }

    public void setStringData ( String stringData ) {}

    public String getSystemId () {
        return systemId;
    }

    public void setSystemId ( String systemId ) {
        this.systemId = systemId;
    }

    public String getPublicId () {
        return null;
    }

    public void setPublicId ( String publicId ) {}

    public String getBaseURI () {
        return null;
    }

    public void setBaseURI ( String baseURI ) {}

    public String getEncoding () {
        return null;
    }

    public void setEncoding ( String encoding ) {}

    public boolean getCertifiedText () {
        return false;
    }

    public void setCertifiedText ( boolean certifiedText ) {}


    private String systemId = null;
    private InputStream byteStream = null;
}

There are quite a few posts regarding this topic and I could not find a satisfying solution either. Here is how it worked for me. Give the SchemaFactory a custom resource resolver


    Source source = new StreamSource(this.getClass().getResourceAsStream("ebics.xsd"));
    LSResourceResolver resolver = new ResourceResolver(schemaFactory.getResourceResolver());
    schemaFactory.setResourceResolver(resolver);
    

and parse only the top level schema. The resolver can then (hopefully) resolve the embedded references


public class ResourceResolver implements LSResourceResolver {
    private LSResourceResolver parent = null;
    private Set returnedResources = new HashSet();


    public ResourceResolver(LSResourceResolver r){
    parent = r;
    }

    private ResourceResolver() {
    }

    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
    LSInput input = new LSInputImpl();

    if (returnedResources.contains(systemId)) {
        return null;
    } else if (systemId.equals("ebics_hev.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_hev.xsd"));
    } else if (systemId.equals("ebics_keymgmt_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_request.xsd"));
    } else if (systemId.equals("ebics_keymgmt_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_keymgmt_response.xsd"));
    } else if (systemId.equals("ebics_orders.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_orders.xsd"));
    } else if (systemId.equals("ebics_request.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_request.xsd"));
    } else if (systemId.equals("ebics_response.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_response.xsd"));
    } else if (systemId.equals("ebics_signature.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_signature.xsd"));
    } else if (systemId.equals("ebics_types.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics_types.xsd"));
    } else if (systemId.equals("ebics.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("ebics.xsd"));
    } else if (systemId.equals("xmldsig-core-schema.xsd")) {
        input.setByteStream(this.getClass().getResourceAsStream("xmldsig-core-schema.xsd"));
    } else {
        return parent.resolveResource(type, namespaceURI, publicId, systemId, baseURI);
    }
    returnedResources.add(systemId);
    return input;
    }

}

Here is the LSInputImpl


public class LSInputImpl implements LSInput
{

    public Reader getCharacterStream () {
        return null;
    }

    public void setCharacterStream ( Reader characterStream ) {}

    public InputStream getByteStream () {
        InputStream retval = null;
        if ( byteStream != null ) {
            retval = byteStream;
        }
        return retval;
    }

    public void setByteStream ( InputStream byteStream ) {
        this.byteStream = byteStream;
    }

    public String getStringData () {
        return null;
    }

    public void setStringData ( String stringData ) {}

    public String getSystemId () {
        return systemId;
    }

    public void setSystemId ( String systemId ) {
        this.systemId = systemId;
    }

    public String getPublicId () {
        return null;
    }

    public void setPublicId ( String publicId ) {}

    public String getBaseURI () {
        return null;
    }

    public void setBaseURI ( String baseURI ) {}

    public String getEncoding () {
        return null;
    }

    public void setEncoding ( String encoding ) {}

    public boolean getCertifiedText () {
        return false;
    }

    public void setCertifiedText ( boolean certifiedText ) {}


    private String systemId = null;
    private InputStream byteStream = null;
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文