SV: [jdom-interest] EntityResolver to resolve relative DTDs

Per Norrman pernorrman at telia.com
Tue Dec 16 16:46:38 PST 2003


Hi,

This isn't really a JDOM question, is it? Anyway, here's an approach:

	Source xmlSource = new StreamSource(<inputstream>, <systemid>);
	Source xslSource = new StreamSource(new URL(xsl).openStream());
	TransformerFactory factory = TransformerFactory.newInstance();
	Transformer transformer = factory.newTransformer(...);

	Result result = new StreamResult(<outputstream>);
	transformer.transform(xmlSource, result);

For <inputstream>, use the one you already have in 
req.getContentObject().getMetadataInputStream(). 

For <systemid>, use your desired absolute uri,
http://myserver.com/dtd/myDTD.dtd or
http://myserver.com/. This system id will be used when resolving a
relative URI, so 
the relative URI in the XML source must exist at the location pointed to
by the
absoulte URI.

For <outputstream>, use the one you already have in 
req.getContentObject().getMetadataOutputStream().

To get the desired encoding, you can specify it in the xsl source:

<xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>

The PUBLICID is just a label. Typically, this label is used to
select a local DTD for validating the xml source and/or take specific
actions
depending on the value. 
An EntityResolver would somehow use the PUBLICID to look up the proper
DTD 
and return an InputSource. For example, I would assume that all Servlet 
containers use the PUBLICID to select local copies of the servlet config

DTD (2.2, 2.3, 2.4, etc).

The SYSTEMID is a URI. If nothing else is specified, the parser will go
there
and try to fetch the DTD.

Finally, I would recommend using a local copy of your DTD. Why would you
want to spend the extra burden of a networked http access, when a local
file
access is all it takes? You can use the same approach as above, just use
a file URI
for the <systemid> parameter, e.g. file:/path/to/myDTD.dtd. You will
also *NOT* be
dependent on the HTTP server availability.

/pmn



-----Ursprungligt meddelande-----
Från: jdom-interest-admin at jdom.org [mailto:jdom-interest-admin at jdom.org]
För Pramodh Peddi
Skickat: den 16 december 2003 18:27
Till: jdom-interest at jdom.org
Ämne: [jdom-interest] EntityResolver to resolve relative DTDs


Hi,

I know there are already a few requests and responses on this topic (and
a couple of them helped me in few instances), but I couldn't get exactly
what I wanted from them. I did not clearly undetsrtand the working of
EntiryResolver. I am using Java1.4's API for Transformation.

Following is what I am doing:
My source xml (which is to be transformed) has a relative URI specified
for DTD(<!DOCTYPE FEED_DTD SYSTEM "myDTD.dtd">). I want the parser to
use an absolute URL ("http://myserver.com/dtd/myDTD.dtd", and not the
"myDTD.dtd" specified inside the source xml) for the DTD to validate the
source xml.

And this is the code I am using to do the above work:
**********************************CODE**********************************
****
******************
public class SELTransformationService{

private String stylesheet;
private String fileName = null;
private String dtdURL = null;

private void transform(String metadata, String stylesheet,
ServiceRequest req, ServiceResponse res){

//System.out.println("TRANSFORM USING STRING");

try {

TransformerFactory tFactory = TransformerFactory.newInstance();

Transformer transformer = tFactory.newTransformer(new StreamSource(new
URL(stylesheet).openStream()));

InputStream inputStream =
req.getContentObject().getMetadataInputStream();

OutputStream outputStream =
req.getContentObject().getMetadataOutputStream();

SAXParserFactory pfactory= SAXParserFactory.newInstance();

pfactory.setValidating(true);

// Get an XMLReader.

XMLReader reader = pfactory.newSAXParser().getXMLReader();

//create a resolver to resolve the DTD in the source xml

//EntityResolver resolver = new DTDResolver();

reader.setEntityResolver(new DTDResolver());

DTDResolver resolver = (DTDResolver)reader.getEntityResolver();

resolver.setPublicId(this.dtdURL);

SAXSource source = new SAXSource(reader,

new InputSource(new InputStreamReader(inputStream)));

source.setSystemId("SonyDAMAssetMetadata.dtd");

transformer.transform(source, new StreamResult(new
OutputStreamWriter(outputStream, "iso-8859-1")));

outputStream.close();

req.getContentObject().commit();

res.send(req.getContentObject());

log.info(fileName + " - OBJECT SENT OUT OF TRANSFORMATION-2");

} catch (Exception ex) {

res.error(req.getContentObject(), "Exception sending message to bus.");

ex.printStackTrace();

}

}//end SELTransformationService classclass DTDResolver implements
EntityResolver {

String publicId = null;

public void setPublicId(String publicId){

this.publicId = publicId;

System.out.println("Setting publicID");

}

public String getPublicId(){

System.out.println("Getting publicId");

return this.publicId;

}

public InputSource resolveEntity (String publicId, String systemId){

InputStream inputStream = null;

InputSource source = null;

try{

System.out.println("publicID is: " + this.publicId);

if(StringUtils.isNotEmpty(this.publicId)){

URL url = new URL(this.publicId);

inputStream = url.openStream();

System.out.println("got the inputstream");

source = new InputSource(new InputStreamReader(inputStream));

}else{

System.out.println("publicId is not specified!!!");

}

}catch(Exception e){

}

return source;

}

}//end DTDResolver class

******************************************************CODE**************
****
*****************************

I am sending the publicID (which is the absolute URL i am asking the
parser to for the DTD) and using that for validation.

It is not throwing any exception, but the transformed stream doesn't
have anything except the header "<?xml version="1.0"
encoding="UTF-8"?>". The header is also not supposed to have UTF-8, it
is supposed to be "iso-8859-1". Can anyone tell me what my mistake is
and what I am missing?

And few questions about the working of EntityResolver ( I went thru the
API, but its not completely clear to me. I was wondering if I can more
clear concepts about EntityResolver):

1. What is the significance of systemID and publicID?

2. What should the InputSource return symantically?



Sorry for the long email and a bunch of questions. Hope i get some help
out of it.

Thanks,

Pramodh.

_______________________________________________
To control your jdom-interest membership:
http://lists.denveronline.net/mailman/options/jdom-interest/youraddr@you
rhost.com




More information about the jdom-interest mailing list