2012-02-01 34 views
5

पकड़ने के लिए जावा में एक्सएसडी का उपयोग करके एक्सएमएल फाइल को कैसे सत्यापित किया जा सकता है? हम पहले से ही स्कीमा नहीं जानते हैं। मैं schemaLocation प्राप्त करने में सक्षम होना चाहता हूं, एक्सएसडी डाउनलोड कर सकता हूं, इसे कैश कर सकता हूं और फिर वास्तविक सत्यापन कर सकता हूं।जावा में एक्सएसडी के खिलाफ एक्सएमएल मान्य करें/स्कीमालोकेशन

समस्या यह है कि javax.xml.parsers.DocumentBuilder/DocumentBuilderFactory कक्षाओं के साथ मैं schemaLocation अग्रिम में पकड़ नहीं पा रहा हूं। इसके लिए क्या चाल है? मुझे किस वर्ग में देखना चाहिए?

शायद एक और उपयुक्त एपीआई है जिसका मैं उपयोग कर सकता हूं? पूरी समस्या यह है कि हमें गतिशील रूप से सत्यापित करने की आवश्यकता है, बिना (जरूरी) एक्सएसडी स्थानीय रूप से।

एक्सएसडी फ़ाइल में परिभाषित schemaLocation के यूआरएल को कैसे पकड़ सकता है?

मुझे पता है कि आप विशेषताएं/विशेषताओं को सेट कर सकते हैं, लेकिन यह एक अलग बात है। मुझे पहले XSD से schemaLocation प्राप्त करने की आवश्यकता है।

कृपया सलाह दें!

उत्तर

4

यह देखते हुए कि आप Xerces (या JDK डिफ़ॉल्ट) का उपयोग कर रहे हैं, क्या आपने इस सुविधा को फैक्ट्री पर सही करने की कोशिश की है: http://apache.org/xml/features/validation/schemahttp://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 का उपयोग कर रहा हूं। दूसरा लिंक काम नहीं करता है। मुझे एक साथ सभी एपीआई का उपयोग करने में कोई फर्क नहीं पड़ता। – carlspring

+0

@carlspring। अद्यतन देखें। –

+0

हाँ, जबकि यह वास्तव में सही है, मेरे पास अभी भी स्कीमा का स्थान नहीं है, इसलिए मैं इसे कैश नहीं कर सकता और मुझे कैशिंग लागू करने की आवश्यकता है। इसलिए मुझे पहले 'स्कीमालोकेशन' को पकड़ने की ज़रूरत है। – carlspring