Parsing an XML file with a DTD schema on a relative path
Asked Answered
A

4

11

I have the following java code:


DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc=db.parse(new File("/opt/myfile"));

And /opt/myfile contains something like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE archive SYSTEM "../../schema/xml/schema.dtd">
...

I get the following error:

java.io.FileNotFoundException: /../schema/xml/schema.dtd (No such file or directory)

This is a large java framework that consumes an XML file produced elsewhere. I think the relative path is the problem. I don't think it will be acceptable to change the cwd before the JVM starts (the path comes from a config file that is read by the JVM itself) and I have not found a way to change the cwd while the JVM is running. How do I parse this XML file with the appropriate DTD?

Animato answered 18/1, 2011 at 16:12 Comment(0)
H
20

You need to use a custom EntityResolver to tweak the path of the DTD so that it can be found. For example:

db.setEntityResolver(new EntityResolver() {
    @Override
    public InputSource resolveEntity(String publicId, String systemId)
            throws SAXException, IOException {
        if (systemId.contains("schema.dtd")) {
            return new InputSource(new FileReader("/path/to/schema.dtd"));
        } else {
            return null;
        }
    }
});

If schema.dtd is on your classpath, you can just use getResourceAsStream to load it, without specifying the full path:

return new InputSource(Foo.class.getResourceAsStream("schema.dtd"));
Herschel answered 18/1, 2011 at 16:37 Comment(1)
Ready to use resolver example: org.hibernate.util.DTDEntityResolverCapriccioso
H
5

You can also ignore the DTD altogether: http://marcels-javanotes.blogspot.com/2005/11/parsing-xml-file-without-having-access.html

Harrier answered 29/11, 2011 at 7:12 Comment(0)
T
1

Below code work for me, It ignore DTD

Imports:

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

Code :

File fileName = new File("XML File Path");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
EntityResolver resolver = new EntityResolver () {
public InputSource resolveEntity (String publicId, String systemId) {
String empty = "";
ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
                    System.out.println("resolveEntity:" + publicId + "|" + systemId);
                    return new InputSource(bais);
                    }
                    };
documentBuilder.setEntityResolver(resolver); 
Document document = documentBuilder.parse(fileName);
Terse answered 6/9, 2019 at 13:48 Comment(1)
Thanks a lot! This saved me time!Adham
D
0

I used the custom EntityResolver like the example above but it still searched the DTD file in another base directory. So I debuged it and then found out I need to change user.dir system property. So I added this line to my application initialization method and it works now.

System.setProperty("user.dir")
Darice answered 22/6, 2016 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.