2012-02-01 95 views
5

如何在Java中使用XSD驗證XML文件?我們事先不知道這個模式。我希望能夠獲得schemaLocation,下載XSD,緩存它,然後執行實際驗證。根據Java中的XSD驗證XML /獲取模式位置

問題是,與javax.xml.parsers.DocumentBuilder/DocumentBuilderFactory類我似乎無法提前獲得schemaLocation持有。這有什麼訣竅?我應該考慮哪些課程?

也許有更適合我的API可以使用?整個問題是,我們需要動態驗證,沒有(必然)在本地擁有XSD。

如何獲取在XSD文件中定義的schemaLocation的URL?

我知道你可以設置特徵/屬性,但這是不同的事情。我需要先從XSD獲取schemaLocation

請指教!

回答

4

鑑於您使用的是Xerces(或JDK默認設置),您是否嘗試在工廠上將此功能設置爲true:http://apache.org/xml/features/validation/schema。還有其他的功能,你可以提供關於模式玩法:http://xerces.apache.org/xerces2-j/features.html

更新2(緩存):

實現一個org.w3c.dom.ls.LSResourceResolver和使用setResourceResolver方法來設置這個就SchemaFactory。該解析器將從緩存中獲取架構或從位置引用的任何位置獲取架構。

更新3:

LSResourceResolver的例子(我想這將是你一個很好的起點):

/** 
* Resolves resources from a base URL 
*/ 
public class URLBasedResourceResolver implements LSResourceResolver { 

private static final Logger log = LoggerFactory 
     .getLogger(URLBasedResourceResolver.class); 

private final URI base; 

private final Map<URI, String> nsmap; 

public URLBasedResourceResolver(URL base, Map<URI, String> nsmap) 
     throws URISyntaxException { 
    super(); 
    this.base = base.toURI(); 
    this.nsmap = nsmap; 
} 

@Override 
public LSInput resolveResource(String type, String namespaceURI, 
     String publicId, String systemId, String baseURI) { 
    if (log.isDebugEnabled()) { 
     String msg = String 
       .format("Resolve: type=%s, ns=%s, publicId=%s, systemId=%s, baseUri=%s.", 
         type, namespaceURI, publicId, systemId, baseURI); 
     log.debug(msg); 
    } 
    if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { 
     if (namespaceURI != null) { 
      try { 
       URI ns = new URI(namespaceURI); 
       if (nsmap.containsKey(ns)) 
        return new MyLSInput(base.resolve(nsmap.get(ns))); 
      } catch (URISyntaxException e) { 
       // ok 
      } 
     } 
    } 
    return null; 
} 

} 

MyLSInput的實現是很無聊:

class MyLSInput implements LSInput { 

private final URI url; 

public MyLSInput(URI url) { 
    super(); 
    this.url = url; 
} 

@Override 
public Reader getCharacterStream() { 
    return null; 
} 

@Override 
public void setCharacterStream(Reader characterStream) { 

} 

@Override 
public InputStream getByteStream() { 
    return null; 
} 

@Override 
public void setByteStream(InputStream byteStream) { 

} 

@Override 
public String getStringData() { 
    return null; 
} 

@Override 
public void setStringData(String stringData) { 

} 

@Override 
public String getSystemId() { 
    return url.toASCIIString(); 
} 

@Override 
public void setSystemId(String systemId) { 
} 

@Override 
public String getPublicId() { 
    return null; 
} 

@Override 
public void setPublicId(String publicId) { 
} 

@Override 
public String getBaseURI() { 
    return null; 
} 

@Override 
public void setBaseURI(String baseURI) { 

} 

@Override 
public String getEncoding() { 
    return null; 
} 

@Override 
public void setEncoding(String encoding) { 

} 

@Override 
public boolean getCertifiedText() { 
    return false; 
} 

@Override 
public void setCertifiedText(boolean certifiedText) { 

} 

} 
+0

關於第一個鏈接 - 我使用xerces:2.10.0作爲JDK之外的獨立Maven依賴項。第二個鏈接不起作用。 我不介意一起使用另一個API。 – carlspring 2012-02-01 14:07:21

+0

@carlspring。查看更新。 – 2012-02-01 14:52:57

+0

是的,雖然這確實是正確的,我仍然沒有模式的位置,因此我無法緩存它,我需要實現緩存。因此,我真的需要先掌握'schemaLocation'。 – carlspring 2012-02-01 15:13:47