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