Validate XML against DTD? XSD OK. SSCCE.

  • Thread starter Andrew Thompson
  • Start date
A

Andrew Thompson

This example* shows how to validate XML against XSD.

What I would *like* to do is also offer validation
against DTD. Unforutnately, when the 'DTD' XMLConstant
is selected in the last dialog (bottom option
http://www.w3.org/TR/REC-xml), I get the output..

"Create schema from 'http://java.sun.com/dtd/JNLP-1.5.dtd'.
Exception in thread "main" java.lang.IllegalArgumentException:
No SchemaFactory that implements the schema language specified by:
http://www.w3.org/TR/REC-xml could be loaded
at javax.xml.validation.SchemaFactory
.newInstance(SchemaFactory.java:207)
..."

Does anybody demonstrate how to validate against DTD?

BTW - A quick search on ..
<http://www.google.com/search?q=XML_DTD_NS_URI+"No+SchemaFactory">
..did not reveal 'much', so I am thinking I
have 'got this all wrong'.

*
<sscce>
import java.io.IOException;

import javax.swing.JOptionPane;
import javax.swing.JComboBox;

import javax.xml.XMLConstants;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Schema;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import org.w3c.dom.Document;

/** Simple example of validating a structured document (XML)
against a schema (XSD).
Can anybody change this to code that will successfully
validate against a DTD? */
class XMLValidate {

public static void main(String[] args) throws
ParserConfigurationException,
SAXException,
IOException
{

String[] contentOptions =
{
// The Player JNLP is meant to pop the Java Control Panel
// It was never intended to be valid accoring to the spec.,
// as such, it is a good 'target' for validation, as it will
// most likely remain 'invalid' according to the DTD/XSD
"http://java.sun.com/products/javawebstart/apps/player.jnlp"
,
// Sun's Java2D Demo - valid at time of check
"http://java.sun.com/products/jfc/jws/Java2Demo.jnlp"
,
// example of loading file from same directory
"file:./xmlv.jnlp"
};

String content = null;

String[] definitionOptions =
{
// the XSD from the PhySci site
"http://www.physci.org/JNLP-6.0.xsd"
,
// DTD for the Sun JNLP format
// **can we create a schema from this?**
"http://java.sun.com/dtd/JNLP-1.5.dtd"
,
// for access from local file-system
"file:../373XMLValidator/xmlvalidate/build/dist/JNLP-6.0.xsd"
};

String definition = null;

String[] languageOptions =
{
// XML
XMLConstants.W3C_XML_SCHEMA_NS_URI
,
//
XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
,
// RelaxNG
XMLConstants.RELAXNG_NS_URI
,
// XPath
XMLConstants.W3C_XPATH_DATATYPE_NS_URI
,
// DTD
// No SchemaFactory that implements the schema language ..
XMLConstants.XML_DTD_NS_URI
};
String language = null;

XMLErrorHandler errorHandler = new XMLErrorHandler();

if (args.length==2) {
content = args[0];
definition = args[1];
} else if (args.length==0) {
JComboBox contentChoice = new JComboBox (contentOptions);
contentChoice.setEditable(true);
JOptionPane.showMessageDialog(
null,
contentChoice,
"XML URL (document)",
JOptionPane.QUESTION_MESSAGE
);
content = (String)contentChoice.getSelectedItem();

JComboBox definitionChoice = new JComboBox (definitionOptions);
definitionChoice.setEditable(true);
JOptionPane.showMessageDialog(
null,
definitionChoice,
"XSD(/DTD) URL (schema definition)",
JOptionPane.QUESTION_MESSAGE
);
definition = (String)definitionChoice.getSelectedItem();

JComboBox languageChoice = new JComboBox (languageOptions);
languageChoice.setEditable(true);
JOptionPane.showMessageDialog(
null,
languageChoice,
"Language - see XMLConstants",
JOptionPane.QUESTION_MESSAGE
);
language = (String)languageChoice.getSelectedItem();
} else {
System.out.println(
"Usage: java XMLValidate "+
"file:./the.xml file:./the.xsd XMLConstants.languages");
System.out.println(
"Usage: java XMLValidate (will prompt for params)");
}
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setFeature("http://xml.org/sax/features/validation", true);
factory.setFeature("http://apache.org/xml/features/validation/schema",
true) ;
factory.setAttribute(
"
http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",
definition);

System.out.println("Create schema from '" + definition + "'.");
SchemaFactory schemaFactory = SchemaFactory.newInstance(language);
Schema schema = schemaFactory.newSchema( new StreamSource(definition) );
factory.setSchema( schema );
System.out.println("Schema created successfully.");

DocumentBuilder documentBuilder = factory.newDocumentBuilder();
documentBuilder.setErrorHandler( errorHandler );

System.out.println("Validate content from '" +
content +
"' against schema.");
try {
Document document = documentBuilder.parse( content );
} catch (SAXException e) {
System.err.println( e.getMessage() );
System.err.println( "Validation failed.." );
}
System.out.println(
"Total (warning, error, fatal) errors detected: " +
errorHandler.getErrorCount() );
}
}

class XMLErrorHandler extends DefaultHandler {

private int errorCount=0;

public void warning(SAXParseException exception)
throws SAXException {
processException(exception);
}

public void error(SAXParseException exception)
throws SAXException {
processException(exception);
}

public void fatalError(SAXParseException exception)
throws SAXException {
processException(exception);
}

public void processException(SAXParseException exception) {
System.err.println(exception);
errorCount++;
}

public int getErrorCount() {
return errorCount;
}
}
</sscce>
 
A

Andrew Thompson

Piotr said:
...
You may also do something I call validation of a rewritten XML against a
given DTD, an example is there:
<http://groups.google.pl/group/comp.lang.java.programmer/msg/ce4940523b837d20?>

I had meant to revisit that. Unfortunately I get along the lines of..

D:\java ValidateJNLP
org.xml.sax.SAXParseException: White space is required after
the element type "update" in the element type declaration.
Exception in thread "main" org.xml.sax.SAXParseException:
White space is required after the element type "update" in
the element type declaration.
at com.sun.org.apache.xerces.internal.parsers.
AbstractSAXParser.parse(AbstractSAXParser.java:1231)
...

How about I/we rework it to a form that can pull the XML/DTD
directly off the net, and upload it to the same directory on
my site? Perhaps that is the better example to continue with.

Also. V. 0.4 of XMLValidate has been uploaded, updating the
JNLP from 1.5 to 6.0 - if it is going to fail for a DTD - it might
as well fail for the current version!

--
Andrew Thompson
http://www.athompson.info/andrew/

Message posted via JavaKB.com
http://www.javakb.com/Uwe/Forums.aspx/java-general/200710/1
 
P

Piotr Kobzda

Andrew said:
I had meant to revisit that. Unfortunately I get along the lines of..

D:\java ValidateJNLP
org.xml.sax.SAXParseException: White space is required after
the element type "update" in the element type declaration.
Exception in thread "main" org.xml.sax.SAXParseException:
White space is required after the element type "update" in
the element type declaration.
at com.sun.org.apache.xerces.internal.parsers.
AbstractSAXParser.parse(AbstractSAXParser.java:1231)
..

My guess is you are probably using invalid DTD with it. Have you
applied mandatory corrections to DTD?

How about I/we rework it to a form that can pull the XML/DTD
directly off the net, and upload it to the same directory on
my site? Perhaps that is the better example to continue with.

See no problem with that.

In addition, you/we have to change the following lines of the example:

XMLEvent e = er.nextEvent();

if (e.isStartElement()) {
// creatre new DTD
DTD dtd = xef.createDTD("<!DOCTYPE jnlp"
+ " SYSTEM \"" + dtd_file.toURI() + "\">");

That implements requirement of JNLP specification for rooting the
document with 'jnlp' element. However, general purpose validator should
rather rewrite a DTD as follows:

DTD dtd = xef.createDTD("<!DOCTYPE "
+ e.asStartElement().getName().getLocalPart()
+ " SYSTEM \"" + dtd_file.toURI() + "\">");


The example requires also to take into consideration at least: 1) XML
namespaces (I never tried that with StAX); 2) rewriting full document is
not necessary, only the DTD part needs to be rewritten, after that the
processing may be streamed; 3) URIs should be resolved a way causing
reading DTD from stream rather than file; ...


P.S.
I e-mailed you twice today, but I'm not sure you received my message...
Anyway, if you think I can help you with extending that somehow, you
are welcome to e-mail me.

My alternative e-mail: pikob (at) op (dot) pl.


piotr
 
A

Andrew Thompson

Andrew said:
This example* shows how to validate XML against XSD.

What I would *like* to do is also offer validation
against DTD. ...

This was actually explained to me some time ago.
<http://www.javakb.com/Uwe/Forum.aspx/java-programmer/37099/JNLP-xsd-schema#f83g34gmf1inewsgazetapl
Because I foolishly used an invalid DTD and did not
look at the stacktrace carefully, I could not get it to
work.

In any case, my reply to that thread updates it to
an URL based example, to show a number of
versions of the JNLP 6 DTD, as well as a few other
DTDs - validating right off your PC at home.

*This* thread is concluded. Thanks for all the help, Piotr!

--
Andrew Thompson
http://www.athompson.info/andrew/

Message posted via JavaKB.com
http://www.javakb.com/Uwe/Forums.aspx/java-general/200710/1
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top