之前写的文章利用到了dom4j,而且是单个的xsd验证。但是项目实际需求是xsd中引用了其他的xsd。即有验证结构的,也有验证内容的。
以下是多个xsd联合验证xml的代码,没有用到dom4j,使用的是java自己的API。
代码是同事的朋友给的,不知出处,如果侵犯到了原作者的权益,请联系我。
Anyway,感谢写出代码的同行,帮我解决了问题。
代码写了三个类文件。
SchemaResourceResolver.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.log4j.Logger;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
/**
*
* Implement LSResourceResolver to customize resource resolution when parsing schemas.
* <p>
* SchemaFactory uses a LSResourceResolver when it needs to locate external resources
* while parsing schemas, although exactly what constitutes "locating external resources"
* is up to each schema language.
* </p>
* <p>
* For example, for W3C XML Schema, this includes files <include>d or <import>ed,
* and DTD referenced from schema files, etc.
*</p>
*
*/
class SchemaResourceResolver implements LSResourceResolver {
private static final Logger log = Logger.getLogger(SchemaResourceResolver. class );
/**
*
* Allow the application to resolve external resources.
*
* <p>
* The LSParser will call this method before opening any external resource, including
* the external DTD subset, external entities referenced within the DTD, and external
* entities referenced within the document element (however, the top-level document
* entity is not passed to this method). The application may then request that the
* LSParser resolve the external resource itself, that it use an alternative URI,
* or that it use an entirely different input source.
* </p>
*
* <p>
* Application writers can use this method to redirect external system identifiers to
* secure and/or local URI, to look up public identifiers in a catalogue, or to read
* an entity from a database or other input source (including, for example, a dialog box).
* </p>
*/
public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
log.info("/n>> Resolving " + "/n"
+ "TYPE: " + type + "/n"
+ "NAMESPACE_URI: " + namespaceURI + "/n"
+ "PUBLIC_ID: " + publicId + "/n"
+ "SYSTEM_ID: " + systemId + "/n"
+ "BASE_URI: " + baseURI + "/n" );
String schemaLocation = baseURI.substring(0 , baseURI.lastIndexOf( "/" ) + 1 );
if (systemId.indexOf( "http://" ) < 0 ) {
systemId = schemaLocation + systemId;
}
LSInput lsInput = new LSInputImpl();
URI uri = null ;
try {
uri = new URI(systemId);
} catch (URISyntaxException e) {
e.printStackTrace();
}
File file = new File(uri);
FileInputStream is = null ;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
lsInput.setSystemId(systemId);
lsInput.setByteStream(is);
return lsInput;
}
/**
*
* Represents an input source for data
*
*/
class LSInputImpl implements LSInput {
private String publicId;
private String systemId;
private String baseURI;
private InputStream byteStream;
private Reader charStream;
private String stringData;
private String encoding;
private boolean certifiedText;
public LSInputImpl() {}
public LSInputImpl(String publicId, String systemId, InputStream byteStream) {
this .publicId = publicId;
this .systemId = systemId;
this .byteStream = byteStream;
}
public String getBaseURI() {
return baseURI;
}
public InputStream getByteStream() {
return byteStream;
}
public boolean getCertifiedText() {
return certifiedText;
}
public Reader getCharacterStream() {
return charStream;
}
public String getEncoding() {
return encoding;
}
public String getPublicId() {
return publicId;
}
public String getStringData() {
return stringData;
}
public String getSystemId() {
return systemId;
}
public void setBaseURI(String baseURI) {
this .baseURI = baseURI;
}
public void setByteStream(InputStream byteStream) {
this .byteStream = byteStream;
}
public void setCertifiedText( boolean certifiedText) {
this .certifiedText = certifiedText;
}
public void setCharacterStream(Reader characterStream) {
this .charStream = characterStream;
}
public void setEncoding(String encoding) {
this .encoding = encoding;
}
public void setPublicId(String publicId) {
this .publicId = publicId;
}
public void setStringData(String stringData) {
this .stringData = stringData;
}
public void setSystemId(String systemId) {
this .systemId = systemId;
}
}
}
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.apache.log4j.Logger;
import org.xml.sax.SAXException;
public final class XMLParser {
private static final Logger log = Logger.getLogger(XMLParser.class);
private XMLParser() {
}
public static boolean validateWithSingleSchema(File xml, File xsd) {
boolean legal = false;
try {
SchemaFactory sf = SchemaFactory
.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = sf.newSchema(xsd);
Validator validator = schema.newValidator();
validator.validate(new StreamSource(xml));
legal = true;
} catch (Exception e) {
legal = false;
log.error(e.getMessage());
}
return legal;
}
public static boolean validateWithMultiSchemas(InputStream xml,
List<File> schemas) {
boolean legal = false;
try {
Schema schema = createSchema(schemas);
Validator validator = schema.newValidator();
validator.validate(new StreamSource(xml));
legal = true;
} catch (Exception e) {
legal = false;
log.error(e.getMessage());
}
return legal;
}
/**
* Create Schema object from the schemas file.
*
* @param schemas
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public static Schema createSchema(List<File> schemas)
throws ParserConfigurationException, SAXException, IOException {
SchemaFactory sf = SchemaFactory
.newInstance("http://www.w3.org/2001/XMLSchema");
SchemaResourceResolver resourceResolver = new SchemaResourceResolver();
sf.setResourceResolver(resourceResolver);
Source[] sources = new Source[schemas.size()];
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
docFactory.setValidating(false);
docFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
for (int i = 0; i < schemas.size(); i++) {
org.w3c.dom.Document doc = docBuilder.parse(schemas.get(i));
DOMSource stream = new DOMSource(doc, schemas.get(i)
.getAbsolutePath());
sources[i] = stream;
}
return sf.newSchema(sources);
}
}
XSLTParser.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class XSLTParser {
public static void xslt(String inFilename, String outFilename,
String xsltFilename) {
try {
// Create transformer factory
TransformerFactory factory = TransformerFactory.newInstance();
// Use the factory to create a template containing the xsl file
Templates template = factory.newTemplates(new StreamSource(
new FileInputStream(xsltFilename)));
// Use the template to create a transformer
Transformer xformer = template.newTransformer();
// Prepare the input and output files
Source source = new StreamSource(new FileInputStream(inFilename));
Result result = new StreamResult(new FileOutputStream(outFilename));
// Apply the xsl file to the source file and write the result to the
// output file
xformer.transform(source, result);
} catch (FileNotFoundException e) {
// File not found
} catch (TransformerConfigurationException e) {
// An error occurred in the XSL file
} catch (TransformerException e) {
// An error occurred while applying the XSL file
// Get location of error in input file
}
}
}
测试方法:
public boolean testValidate() throws SAXException,
FileNotFoundException {
InputStream xml = new FileInputStream(new File("data.xml"));
List<File> schemas = new ArrayList<File>();
schemas.add(new File("DeclarationTypeCode.xsd"));
schemas.add(new File("HeadDefine.xsd"));
schemas.add(new File("DateTimeDefine.xsd"));
// schemas.add(new File("DeclarationDefine.xsd"));
schemas.add(new File("base.xsd"));
return XMLParser.validateWithMultiSchemas(xml, schemas);
}
在base.xsd中import了HeadDefine.xsd和DeclarationDefine.xsd,
在HeadDefine.xsd中又import了DeclarationTypeCode.xsd
在DeclarationDefine.xsd中又import了DateTimeDefine.xsd
测试结果,此测试方法返回true则验证成功,返回false则验证失败。