Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transformer library that comes with Java converts spaces in file paths to %20

Here is a test application that writes out XML Files.

Why are the spaces in my path being converted to %20?

public class XmlTest
{
    public static void main(String[] args)
    {
        String filename = "C:\\New Folder\\test.xml";
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            DOMSource source = new DOMSource(doc);

            File xmlFile = new File(filename);
            if (xmlFile.exists())
            {
                xmlFile.delete();
            }
            StreamResult result = new StreamResult(xmlFile);
            transformer.transform(source, result);

        }
        catch (ParserConfigurationException ex)
        {
            ex.printStackTrace();
        }
        catch (TransformerException tfe)
        {
            tfe.printStackTrace();
        }
    }
}

Stacktrace:

java.io.FileNotFoundException: C:\New%20Folder\test.xml (The system cannot find the path specified)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
    at org.apache.xalan.transformer.TransformerIdentityImpl.createResultContentHandler(TransformerIdentityImpl.java:287)
    at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:330)
    at avm.trans.xml.XmlTest.main(XmlTest.java:52)
like image 388
MxLDevs Avatar asked Dec 06 '13 22:12

MxLDevs


People also ask

How to convert path to file in Java?

The Java Path interface provides to* methods to convert Path -> File. The Path.toFile () converts java.nio.file.Path to java.io.File The File.toPath () method from File class is used to convert java.io.File to java.nio.file.Path

What is transformer class in Java?

Class Transformer. java.lang.Object. javax.xml.transform.Transformer. public abstract class Transformer extends Object An instance of this abstract class can transform a source tree into a result tree. An instance of this class can be obtained with the TransformerFactory.newTransformer method.

What is transformerexception in Java?

TransformerException - If an unrecoverable error occurs during the course of the transformation. public abstract void setParameter ( String name, Object value) Add a parameter for the transformation. Pass a qualified name as a two-part string, the namespace URI enclosed in curly braces ( {}), followed by the local name.

How do I get an instance of the transformer class?

An instance of this class can be obtained with the TransformerFactory.newTransformer method. This instance may then be used to process XML from a variety of sources and write the transformation output to a variety of sinks. An object of this class may not be used in multiple threads running concurrently.


3 Answers

Try to change this line:

StreamResult result = new StreamResult(xmlFile);

into this:

StreamResult result = new StreamResult(new FileOutputStream(xmlFile));

I have no Idea, why the filename is handled as an URL.

like image 107
Christian Kuetbach Avatar answered Oct 10 '22 11:10

Christian Kuetbach


Following from @ChristianKuetbach's answer, it would seem like the argument passed to the StreamResult constructor determines how it will be handled.

From the Oracle docs

public StreamResult(String systemId)  
    Construct a StreamResult from a URL.  
Parameters:  
    systemId - Must be a String that conforms to the URI syntax.

public StreamResult(File f)
   Construct a StreamResult from a File.
Parameters:
   f - Must a non-null File reference.

So initially, I was passing a String path, and so presumably the StreamResult decided to take the initiative to encode it automatically, rather than assuming it is "a String that comforms to the URI syntax".

As a result, passing in a File object told it to handle it as a file path instead of a URL and therefore spaces (and other special characters) were not encoded.

like image 3
MxLDevs Avatar answered Oct 10 '22 11:10

MxLDevs


This problem might also occur in cases of paths containing special characters, for which the first answer isn't helping pretty much(with the conversion, that is). For example, in my case the path of my file contained the char "`" that was automatically translated into "%60".

I solved my problem by changing the code line:

StreamResult result = new StreamResult(xmlFile);

result = D:/Work/.../%60Projects/.../xmlFile.xml

into code lines:

StreamResult result = new StreamResult(xmlFile);
result.setSystemId(URLDecoder.decode(xmlFile.toURI().toURL().toString(), "UTF-8"));

result = D:/Work/.../`Projects/.../xmlFile.xml

This overrides the URL encoding problem that's implemented by default within the StreamResult class.

like image 2
launique Avatar answered Oct 10 '22 10:10

launique