Validating XML with an external DTD

S

salimk786

Hello,

I need help validating an xml file against an external DTD. The below
code allows me to read the xml file and gather specific elements of
interest.

If the xml looked like this, How would i validate it ?
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<simpsons type='bank' platform='TV' app-version='1.0.0'>
<header>
<id>845314490</id>
<title>IN_SF_EN_MA_G2_CA_2009_00</title>
</header>
<font-table>
<font-entry number='1'>
<charset>ansi</charset>
<name>Arial</name>
<pitch>default</pitch>
</font-entry>
<font-entry number='2'>
<charset>ansi</charset>
<name>Times New Roman</name>
<pitch>variable</pitch>
<family>roman</family>
</font-entry>
</font-table>
....
</simpsons>


Thanks.

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

public class ParseXml extends DefaultHandler{

private SAXParserFactory spf;
private Examview tempExamviewObj; //to maintain context

private List myExamviewArrayList;

private String tempVal;
private String filename;

public ParseXml(){
this.myExamviewArrayList = new ArrayList();
}
public Iterator getExamviewIterator(){
return myExamviewArrayList.iterator();
}
public void parse(String filename) {
this.filename = filename;
parseDocument(filename);
}
private void parseDocument(String filename) {

//get a factory
this.spf = SAXParserFactory.newInstance();
try {

//get a new instance of parser
SAXParser sp = this.spf.newSAXParser();

//parse the file and also register this class for call backs
sp.parse(filename, this);

}catch(SAXException se) {
se.printStackTrace();
}catch(ParserConfigurationException pce) {
pce.printStackTrace();
}catch (IOException ie) {
ie.printStackTrace();
}
}

//Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//reset
tempVal = "";
if(qName.equalsIgnoreCase("examview")) {
//create a new instance of Examview
tempExamviewObj = new Examview();
tempExamviewObj.setPlatform(attributes.getValue("platform"));
tempExamviewObj.setAppVersion(attributes.getValue("app-version"));
}
}


public void characters(char[] ch, int start, int length) throws
SAXException {
tempVal = new String(ch,start,length);
}

public void endElement(String uri, String localName, String qName)
throws SAXException {

if(qName.equalsIgnoreCase("Examview")) {
tempExamviewObj.setFileName(this.filename);

//add it to the list
myExamviewArrayList.add(tempExamviewObj);

}else if (qName.equalsIgnoreCase("id")) {
tempExamviewObj.setId(tempVal);
}else if (qName.equalsIgnoreCase("title")) {
tempExamviewObj.setTitle(tempVal);
}else if (qName.equalsIgnoreCase("topic")) {
//System.out.println("Topic:" + tempVal.trim());
tempExamviewObj.addTopic(tempVal);
}else if (qName.equalsIgnoreCase("question")) {
tempExamviewObj.updateQuestionCount();
}

}
}
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

salimk786 said:
I need help validating an xml file against an external DTD. The below
code allows me to read the xml file and gather specific elements of
interest.

I believe that to validate a XML file against a DTD, then you XML file
needs to refer to the DTD - your app can only map from the name used to
a physical location.

You can specify a location of a schema and validate against that
purely in your code.

Arne
 
S

salimk786

I believe that to validate a XML file against a DTD, then you XML file
needs to refer to the DTD - your app can only map from the name used to
a physical location.

You can specify a location of a schema and validate against that
purely in your code.

Arne

I don't have any control over the XML file (i.e. where the dtd
references, or whether it is
a standalone=yes/no document). All I am given is the xml you see
above. I have a simpsons.dtd file which i would like use to validate
the xmls against. I just don't know how to do this.

Thanks
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

salimk786 said:
I don't have any control over the XML file (i.e. where the dtd
references, or whether it is
a standalone=yes/no document). All I am given is the xml you see
above. I have a simpsons.dtd file which i would like use to validate
the xmls against. I just don't know how to do this.

You could sneak a DTD declaration into the stream
you give to the parser via a wrapper class.

Arne
 
S

salimk786

You could sneak a DTD declaration into the stream
you give to the parser via a wrapper class.

Arne

Hello Arne,

Okay, a wrapper class, so how would i do this ? Can you give me some
direction please. I'm still learning java. Much appreciated.

Thanks.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

salimk786 said:
Okay, a wrapper class, so how would i do this ? Can you give me some
direction please. I'm still learning java. Much appreciated.

The following is far from product quality but it should give
you an idea:

Document doc = db.parse(new FakeInputStream("C:\\medarbejder_nodtd.xml",
"<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>\r\n",
"<!DOCTYPE medarbejderliste SYSTEM \"medarbejder.dtd\">\r\n"));

where:

class FakeInputStream extends InputStream {
private static final int F = 1;
private static final int X = 2;
private static final int D = 3;
private InputStream f;
private InputStream x;
private InputStream d;
private int mode;
public FakeInputStream(String xmlfnm, String xmldecl, String
doctyp) throws IOException {
f = new FileInputStream(xmlfnm);
while(f.read() != '\n');
x = new ByteArrayInputStream(xmldecl.getBytes());
d = new ByteArrayInputStream(doctyp.getBytes());
mode = X;
}
public int read() throws IOException {
int c = -1;
switch(mode) {
case X:
c = x.read();
if(c < 0) {
mode = D;
c = d.read();
}
break;
case F:
c = f.read();
break;
case D:
c = d.read();
if(c < 0) {
mode = F;
c = f.read();
}
break;
}
return c;
}
}

Arne
 
T

Twisted

public int read() throws IOException {
int c = -1;
switch(mode) {
case X:
c = x.read();
if(c < 0) {
mode = D;
c = d.read();
if (c < 0) {
mode = F
c = f.read();
}
}
break;
case F:
c = f.read();
break;
case D:
c = d.read();
if(c < 0) {
mode = F;
c = f.read();
}
break;
}
return c;
}

Should not blow up if the DTD string is empty this way. :) (It already
looks to throw IOException and NPE eagerly on failure)
 

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,755
Messages
2,569,537
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top