Reputation: 33
I have problems with validating the xml file against xml schema in case when xml document contains schema. The xml file looks like:
<?xml version="1.0"?>
<catalog xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:x="urn:book">
<!-- START OF SCHEMA -->
<xsd:schema targetNamespace="urn:book">
<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="genre" type="xsd:string"/>
<xsd:element name="price" type="xsd:float"/>
<xsd:element name="publish_date" type="xsd:date"/>
<xsd:element name="description" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<!-- END OF SCHEMA -->
<x:book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with
XML.</description>
</x:book>
</catalog>
java code looks like:
// define the type of schema - we use W3C:
String schemaLang = "http://www.w3.org/2001/XMLSchema";
// get validation driver:
SchemaFactory factory = SchemaFactory.newInstance(schemaLang);
// create schema by reading it from an XSD file:
Schema schema = factory.newSchema(new StreamSource("..........."));
Validator validator = schema.newValidator();
// at last perform validation:
validator.validate(new StreamSource("myDoc.xml"));
And the problem for me is how to use SchemaFactory object in this case ?
I'm greatful for any help!
Upvotes: 1
Views: 1990
Reputation: 163262
As an alternative to Gardea's solution (which is fine except that I have an aversion to anything that involves using the DOM), you could do a transformation to extract the schema and the book element as separate documents before validating one against the other. I mention this because transforming-before-validating is an underused design pattern.
Upvotes: 0
Reputation: 21638
I assume this is what you want; the code is meant to illustrate, rather than account for good programming practices. It was tested with your XML. The main assumption is that the document element has two elements, first one the XSD, second the XML to validate.
If, for example, you change 44.95 to d44.95 you will get this output:
XML is not valid because cvc-datatype-valid.1.2.1: 'd44.95' is not a valid value for 'float'.
Otherwise, everything goes fine and the program prints XML is valid.
import java.io.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.*;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.xpath.*;
import org.xml.sax.InputSource;
public class TestValidation {
public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xpath.evaluate("/*/*", new InputSource("XmlWithEmbeddedXsd.xml"), XPathConstants.NODESET);
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Validator validator = factory.newSchema(new DOMSource(nodes.item(0))).newValidator();
try {
validator.validate(new DOMSource(nodes.item(1)));
System.out.println("XML is valid.");
}
catch (SAXException ex) {
System.out.println("XML is not valid because " + ex.getMessage());
}
}
}
Upvotes: 2