2016-04-28 91 views
0

我试图为模式实现xsd验证程序,即使用导入并包含。例如,我拿了this answer通过解析资源关闭流

这是我的验证方法,包括:

public void validate(String filePath, String schemaName) throws Exception 
{ 
    SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
    factory.setResourceResolver(new ResourceResolver()); 
    Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName)); 
    Schema schema = factory.newSchema(schemaFile); 
    Validator validator = schema.newValidator(); 
    validator.setErrorHandler(new MySAXParseErrorHandler()); 
    validator.validate(new StreamSource(filePath)); 
} 

LSInput中(完全相同):

public class LSInputImpl implements LSInput 
{ 

private String publicId; 

private String systemId; 

public String getPublicId() 
{ 
    return publicId; 
} 

public void setPublicId(String publicId) 
{ 
    this.publicId = publicId; 
} 

public String getBaseURI() 
{ 
    return null; 
} 

public InputStream getByteStream() 
{ 
    return null; 
} 

public boolean getCertifiedText() 
{ 
    return false; 
} 

public Reader getCharacterStream() 
{ 
    return null; 
} 

public String getEncoding() 
{ 
    return null; 
} 

public String getStringData() 
{ 
    synchronized (inputStream) { 
     try { 
      byte[] input = new byte[inputStream.available()]; 
      inputStream.read(input); 
      String contents = new String(input); 
      return contents; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.out.println("Exception " + e); 
     } 
     return null; 
    } 
} 

public void setBaseURI(String baseURI) 
{ 
} 

public void setByteStream(InputStream byteStream) 
{ 
} 

public void setCertifiedText(boolean certifiedText) 
{ 
} 

public void setCharacterStream(Reader characterStream) 
{ 
} 

public void setEncoding(String encoding) 
{ 
} 

public void setStringData(String stringData) 
{ 
} 

public String getSystemId() 
{ 
    return systemId; 
} 

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

public BufferedInputStream getInputStream() 
{ 
    return inputStream; 
} 

public void setInputStream(BufferedInputStream inputStream) 
{ 
    this.inputStream = inputStream; 
} 

private BufferedInputStream inputStream; 

public LSInputImpl(String publicId, String sysId, InputStream input) 
{ 
    this.publicId = publicId; 
    this.systemId = sysId; 
    this.inputStream = new BufferedInputStream(input); 
} 

}

ResourceResolver:

public class ResourceResolver implements LSResourceResolver 
{ 

    public LSInput resolveResource(String type, String namespaceURI, 
          String publicId, String systemId, String baseURI)  { 


    InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(systemId);  
    return new LSInputImpl(publicId, systemId, resourceAsStream); 
} 

}

当我试图验证与只有导入的xsd的xml,它工作正常。但是当我通过使用包括两个分开一个模式,过程失败,IOException异常:

java.io.IOException: Stream closed 
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:159) 
at java.io.BufferedInputStream.available(BufferedInputStream.java:410) 
at LSInputImpl.getStringData(LSInputImpl.java:57) 
at com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper.resolveEntity(DOMEntityResolverWrapper.java:130) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.resolveEntity(XMLEntityManager.java:1073) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.resolveDocument(XMLSchemaLoader.java:659) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.resolveSchemaSource(XSDHandler.java:2105) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1088) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1120) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:620) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540) 
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:255) 
at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:638) 
at Main.validate(Main.java:54) 
at Main.main(Main.java:68) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:483) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 

org.xml.sax.SAXParseException; systemId: file:///C:/Users/adobryn/Java/sub/schema.xsd; lineNumber: 456; columnNumber: 73; src-resolve: Cannot resolve the name 'st_Term' to a(n) 'type definition' component. 
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) 
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134) 
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4162) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4145) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1741) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(XSDElementTraverser.java:405) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseLocal(XSDElementTraverser.java:194) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseLocalElements(XSDHandler.java:3618) 
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:633) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574) 
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540) 
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:255) 
at javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:638) 
at Main.validate(Main.java:54) 
at Main.main(Main.java:68) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:483) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 

架构,则包括:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/schema" targetNamespace="http://www.w3.org/schema" elementFormDefault="qualified">  
    <xsd:include schemaLocation="st_Term.xsd"/> 
    <xsd:element name="Term" type="st_Term" minOccurs="0" maxOccurs="1"/> 
</xsd:schema> 

我想,有什么不对的getStringData()方法。我如何修改它?谢谢你的帮助!

+0

您在Javadoc中专门警告您使用'InputStream.available()',并且你忽略了'InputStream.read()'的结果,它可能只有1,或者-1。 – EJP

回答

1

的问题是,所包含的XSD还有一个包含,并且ResourceResolver在资源文件夹中查找它,而不是resources/sub,其中包含xsd。所以,我举了另一个例子,它有path tracking,它现在可以工作:)请注意,schemaBasePath应该以“/”开头

-1

几年前,我在包含.xsd中遇到了同样的问题。

我记得我的问题是,.xsd资源及其包含位于资源内的某个包(目录)中。

我用下面的ResourceResolver所在的包被传递给构造函数(resourceRoot参数)解决了这个问题:

class ResourceResolver implements LSResourceResolver { 

    private String resourceRoot; 

    public ResourceResolver(String resourceRoot) { 
     this.resourceRoot = resourceRoot; 
    } 

    public LSInput resolveResource(String type, String namespaceURI,String publicId, String systemId, String baseURI) { 
     InputStream resourceAsStream = this.getClass().getResourceAsStream(resourceRoot + "/" + systemId); 
     return new Input(publicId, systemId, resourceAsStream); 
    } 

} 

和输入:

static class Input implements LSInput { 

    private String publicId; 

    private String systemId; 

    public String getPublicId() { 
     return publicId; 
    } 

    public void setPublicId(String publicId) { 
     this.publicId = publicId; 
    } 

    public String getBaseURI() { 
     return null; 
    } 

    public InputStream getByteStream() { 
     return null; 
    } 

    public boolean getCertifiedText() { 
     return false; 
    } 

    public Reader getCharacterStream() { 
     return null; 
    } 

    public String getEncoding() { 
     return null; 
    } 

    public String getStringData() { 
     synchronized (inputStream) { 
      try { 
       byte[] input = new byte[inputStream.available()]; 
       inputStream.read(input); 
       String contents = new String(input, "UTF-8"); 
       return contents; 
      } catch (IOException e) { 
       e.printStackTrace(); 
       System.out.println("Exception " + e); 
       return null; 
      } 
     } 
    } 

    public void setBaseURI(String baseURI) { 
    } 

    public void setByteStream(InputStream byteStream) { 
    } 

    public void setCertifiedText(boolean certifiedText) { 
    } 

    public void setCharacterStream(Reader characterStream) { 
    } 

    public void setEncoding(String encoding) { 
    } 

    public void setStringData(String stringData) { 
    } 

    public String getSystemId() { 
     return systemId; 
    } 

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

    private final BufferedInputStream inputStream; 

    public Input(String publicId, String sysId, InputStream input) { 
     this.publicId = publicId; 
     this.systemId = sysId; 
     this.inputStream = new BufferedInputStream(input); 
    } 
} 
+0

您对'InputStream.available()'的使用在Javadoc中被特别警告,并且您忽略了'InputStream.read()'的结果,该结果可能只有1,实际上可能是-1。 – EJP