2012-02-01 14 views
5

JavaでXSDを使用してXMLファイルを検証するにはどうすればよいですか?スキーマは事前にわかりません。私はschemaLocationを入手し、XSDをダウンロードし、キャッシュしてから実際の検証を実行できるようにしたいと考えています。JavaでXSDに対してXMLを検証する/ schemaLocationを保持する

問題は、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

UPDATE 2:あなたはに関するスキーマと遊ぶことができる他の機能があります

org.w3c.dom.ls.LSResourceResolverを実装し、setResourceResolver方法を使用してSchemaFactoryでこれを設定します。このリゾルバは、キャッシュからスキーマを取得するか、場所が参照されている場所からスキーマを取得します。

UPDATE 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依存関係として使用しています。 2番目のリンクは機能しません。 別のAPIを一緒に使用しても構いません。 – carlspring

+0

@ carlspring。更新を参照してください。 –

+0

これは確かに正しいですが、まだスキーマの場所がないため、キャッシュできず、キャッシュを実装する必要があります。したがって、私は本当に 'schemaLocation'を最初に保持する必要があります。 – carlspring

関連する問題