86

このメソッドで xml ファイル (変数 f) を解析すると、エラーが発生します

C:\Documents and Settings\joe\Desktop\aicpcudev\OnlineModule\map.dtd (指定されたパスが見つかりません)

私は dtd を持っていないし、必要もないことを知っています。DTD 参照エラーを無視して、この File オブジェクトを Document オブジェクトに解析するにはどうすればよいですか?

private static Document getDoc(File f, String docId) throws Exception{
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(f);


    return doc;
}
4

7 に答える 7

144

DocumentBuilderFactory で機能を設定してみてください。

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

DocumentBuilder db = dbf.newDocumentBuilder();
...

最終的に、オプションはパーサーの実装に固有のものだと思います。それが役立つ場合は、Xerces2 のドキュメントを次に示します。

于 2008-10-01T01:39:58.200 に答える
59

@anjanbによって提案されたものと同様のアプローチ

    builder.setEntityResolver(new EntityResolver() {
        @Override
        public InputSource resolveEntity(String publicId, String systemId)
                throws SAXException, IOException {
            if (systemId.contains("foo.dtd")) {
                return new InputSource(new StringReader(""));
            } else {
                return null;
            }
        }
    });

空の InputSource を返すだけでも同じように機能することがわかりましたか?

于 2008-09-30T22:19:26.357 に答える
6

DTD ファイルが XML と一緒に jar ファイルに含まれているという問題が見つかりました。次のように、ここの例に基づいて問題を解決しました。

DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        if (systemId.contains("doc.dtd")) {
             InputStream dtdStream = MyClass.class
                     .getResourceAsStream("/my/package/doc.dtd");
             return new InputSource(dtdStream);
         } else {
             return null;
         }
      }
});
于 2011-04-28T13:34:04.757 に答える
4

ソース XML (DTD あり)

<!DOCTYPE MYSERVICE SYSTEM "./MYSERVICE.DTD">
<MYACCSERVICE>
   <REQ_PAYLOAD>
      <ACCOUNT>1234567890</ACCOUNT>
      <BRANCH>001</BRANCH>
      <CURRENCY>USD</CURRENCY>
      <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
   </REQ_PAYLOAD>
</MYACCSERVICE>

上記の XML を文字列として受け入れ、DTD 宣言を削除するための Java DOM 実装

public Document removeDTDFromXML(String payload) throws Exception {

    System.out.println("### Payload received in XMlDTDRemover: " + payload);

    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        dbf.setValidating(false);
        dbf.setNamespaceAware(true);
        dbf.setFeature("http://xml.org/sax/features/namespaces", false);
        dbf.setFeature("http://xml.org/sax/features/validation", false);
        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
        is.setCharacterStream(new StringReader(payload));
        doc = db.parse(is); 

    } catch (ParserConfigurationException e) {
        System.out.println("Parse Error: " + e.getMessage());
        return null;
    } catch (SAXException e) {
        System.out.println("SAX Error: " + e.getMessage());
        return null;
    } catch (IOException e) {
        System.out.println("IO Error: " + e.getMessage());
        return null;
    }
    return doc;

}

宛先 XML (DTD なし)

<MYACCSERVICE>
   <REQ_PAYLOAD>
      <ACCOUNT>1234567890</ACCOUNT>
      <BRANCH>001</BRANCH>
      <CURRENCY>USD</CURRENCY>
      <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
   </REQ_PAYLOAD>
</MYACCSERVICE> 
于 2016-11-10T14:00:55.983 に答える
2

私は dtd を持っていないし、必要もないことを知っています。

私はこの声明を疑っています。ドキュメントにエンティティ参照が含まれていますか? もしそうなら、間違いなくDTDが必要です。

とにかく、これが起こらないようにする通常の方法は、XML カタログを使用して「map.dtd」のローカル パスを定義することです。

于 2008-09-30T21:13:44.033 に答える
2

同じ問題を抱えた別のユーザーがいます: http://forums.sun.com/thread.jspa?threadID=284209&forumID=34

その投稿のユーザーddssotは言う

myDocumentBuilder.setEntityResolver(new EntityResolver() {
          public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId)
                 throws SAXException, java.io.IOException
          {
            if (publicId.equals("--myDTDpublicID--"))
              // this deactivates the open office DTD
              return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
            else return null;
          }
});

ユーザーはさらに、「ご覧のとおり、パーサーが DTD にヒットすると、エンティティ リゾルバーが呼び出されます。特定の ID で DTD を認識し、実際の DTD ではなく空の XML ドキュメントを返し、すべての検証を停止します...」と述べています。

お役に立てれば。

于 2008-09-30T22:11:49.480 に答える