【问题标题】:Parsing an XML file with a DTD schema on a relative path使用相对路径上的 DTD 模式解析 XML 文件
【发布时间】:2011-01-18 16:12:58
【问题描述】:

我有以下java代码:

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

/opt/myfile 包含类似:

../../schema/xml/schema.dtd"> ...

我收到以下错误:

java.io.FileNotFoundException: /../schema/xml/schema.dtd (没有这样的文件或目录)

这是一个大型 Java 框架,它使用在其他地方生成的 XML 文件。我认为相对路径是问题所在。我认为在 JVM 启动之前更改 cwd 是不可接受的(路径来自 JVM 本身读取的配置文件),并且我还没有找到在 JVM 运行时更改 cwd 的方法。如何使用适当的 DTD 解析这个 XML 文件?

【问题讨论】:

    标签: java xml dtd


    【解决方案1】:

    您需要使用自定义 EntityResolver 来调整 DTD 的路径,以便可以找到它。例如:

    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;
            }
        }
    });
    

    如果schema.dtd 在您的类路径中,您可以直接使用getResourceAsStream 加载它,而无需指定完整路径:

    return new InputSource(Foo.class.getResourceAsStream("schema.dtd"));
    

    【讨论】:

    【解决方案2】:
    【解决方案3】:

    下面的代码对我有用,它忽略了 DTD

    进口:

    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;
    

    代码:

    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);
    

    【讨论】:

    • 非常感谢!这节省了我的时间!
    【解决方案4】:

    我像上面的示例一样使用了自定义 EntityResolver,但它仍然在另一个基本目录中搜索 DTD 文件。所以我调试了它,然后发现我需要更改 user.dir 系统属性。所以我将这一行添加到我的应用程序初始化方法中,它现在可以工作了。

    System.setProperty("user.dir")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-28
      • 1970-01-01
      • 2011-04-04
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-23
      相关资源
      最近更新 更多