Link to home
Start Free TrialLog in
Avatar of csound
csound

asked on

XML

Can anyone please tell me how to convert from Document to String in XML? I know t.transform(new DOMSource(doc),new StreamResult(new FileOutputStream(file))); will will output the result into a file but how can I get a String result without writing on to  the file?

Also, when I am writing XML to a file I am specifiying DTD in absolute path like

File dsystem=new File("."+sp+"xml"+sp+"symbol.dtd");
     t.setOutputProperty("doctype-system",
                   "file://"+sp+sp+dsystem.getCanonicalPath()
                   );

but when I move the program to  different directory, the program can not locate the DTD file. Does anyone have any idea how to overcome this problem?

Thanx

Document doc = buildDocument();
     
     Transformer t = TransformerFactory
            .newInstance().newTransformer();
            String sp=File.separator;
File dsystem=new File("."+sp+"xml"+sp+"symbol.dtd");
     t.setOutputProperty("doctype-system",
                   "file://"+sp+sp+dsystem.getCanonicalPath()
                   );

     t.transform(new DOMSource(doc),
              new StreamResult(new FileOutputStream(file)));
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of csound
csound

ASKER

->objects
Thanks for your comment but do  you know the answer for the second part of the question?

Thanx
 For the second part you need the file in format:

  file://C/dtdfile.dtd

Avatar of csound

ASKER

Yes I know that. My question is that if another user reads the Xml file in a different computer, the program would not able to read it if there isn't the DTD file in the directory specified.  Likewise, even if we specify the location of the DTD within the program directory, like what i did, if we move the program to a different directory then, again the program would not able to find the DTD file specified.

P.S
I made a small mistake in my program
  t.setOutputProperty("doctype-system",
                  "file://"+dsystem.getCanonicalPath()
                  );
 Why don't you have the DTD somewher on the webserver then and people can access it from wherever they are?
1. Use
StringWriter sw = new StringWriter();
t.transform(new DOMSource(doc),new StreamResult(sw));
String doc = sw.toString();

2. You can resolve the DTD using setEntityResolver on your reader, allowing you to alter the location of the DTD, but you should prefer the principle of gironis' suggestion.
Avatar of csound

ASKER

->girionis
But then computers need to be connected to the Internet when using the program.
True
> But then computers need to be connected to the Internet when using the program.

  Yes. If not try CEHJ's approach.
Why not jar up the DTD with the program and use my second suggestion? That way, it'll always be there.
Avatar of csound

ASKER

->CEHJ
This is my code to parse XML file.

DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder builder = factory.newDocumentBuilder();


Document doc = builder.parse(file);
     
So, if I have the DTD file in the directory, say "C:/test.dtd", what can I put for the argument for the setEntityResolver method?  

builder.setEntityResolver(?):


Here's something i found showing how it's set:

import org.apache.xerces.parsers.DOMParser;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import java.io.PrintWriter;

public class Test {

  public static void main(String[] args) {
    try {
      DOMParser parser = new DOMParser();
      parser.parse(new InputSource(args[0]));
      parser.setEntityResolver(XmlUtils.getLocalEntityResolver());
      Document doc = parser.getDocument();
      NodeList images = doc.getElementsByTagName("img");
      processNodeList(images);
      XmlUtils.serializeXhtml(doc,"new-q.htm");

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  static void processNodeList(NodeList nodes){
    for(int i= 0;i < nodes.getLength();i++){
      Element elem = (Element) nodes.item(i);
      if (elem.getAttribute("src").equals("qbtn1.gif")) {
        elem.setAttribute("alt","question");
      }
    }
  }


}

Avatar of csound

ASKER

->In your case, you need
http://java.sun.com/j2se/1.4/docs/api/javax/xml/parsers/DocumentBuilder.html#setEntityResolver(org.xml.sax.EntityResolver) 

yes I knew that
->builder.setEntityResolver(?):

but I didn't know what to pass in this method. From the API I know I have to pass EntityResolver but I got confused here. With the example I wrote before, what kind of EntityResolver should I use? it would be great if you could provide me some codes. Thanx

->So, if I have the DTD file in the directory, -say "C:/test.dtd", what can I put for the argument for the setEntityResolver method?  

I'll have a look. I think i wrote a util somewhere...
Here we are - an inner class of a utility class i wrote. In your case, you'd maybe want to open a stream on the DTD inside the jar:

/**
   * Allows system ids in doctype declarations to be read locally.
   * In this case, we get system id from the current directory
   *
   * @author     protean
   * @created    26 July 2002
   */
  private static class LocalEntityResolver implements org.xml.sax.EntityResolver {

    /**
     *Description of the Method
     *
     * @param  publicId  Public id of DTD
     * @param  systemId  System id of DTD
     * @return           An input source opened on the local DTD
     */
    public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) {
      try {
        String localId = "./" + systemId.substring(systemId.lastIndexOf("/") + 1);
        //DEBUG

        //System.out.println("Resolved entity " + systemId);
        //System.out.println("To " + localId);
        return new org.xml.sax.InputSource(new java.io.FileReader(localId));
      } catch (java.io.IOException e) {
        e.printStackTrace();
        return null;
      }

    }

  }
Incidentally, one of the reasons i wrote that was so i didn't have to be connected to the network to get the DTD ;-)
Avatar of csound

ASKER

->object
Thanx for your help.

->CEHJ
Thanx for your help. Please find a question titled "To CEHJ". I will give some points there. =)
Thanks for the points :)