3

我正在尝试使用Java 中的 W3C DOM API读取 XML 文档并将其输出到新的 XML 文档中。为了处理 DOCTYPE,我使用以下代码(从输入 Documentdoc到目标 File target):

TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); // omit '<?xml version="1.0"?>'
trans.setOutputProperty(OutputKeys.INDENT, "yes");

// if a doctype was set, it needs to persist
if (doc.getDoctype() != null) {
    DocumentType doctype = doc.getDoctype();
    trans.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctype.getSystemId());
    trans.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctype.getPublicId());
}

FileWriter sw = new FileWriter(target);
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);

这对带有和不带有 DOCTYPE 的 XML 文档都适用。但是,我现在NullPointerException在尝试转换以下输入 XML 文档时遇到了一个问题:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE permissions >
<permissions>
  // ...
</permissions>

HTML 5 对其 DOCTYPE 使用类似的语法,并且它是有效的. 但我不知道如何使用 W3C DOM API 来处理这个问题——试图将其设置DOCTYPE_SYSTEMnull抛出异常。我还可以使用 W3C DOM API 来输出一个空的文档类型吗?

4

2 回答 2

4

虽然这个问题是两年前的问题,但它是一些网络搜索引擎的热门搜索结果,所以也许它是一个有用的捷径。请参阅参考http://www.w3.org/html/wg/drafts/html/master/syntax.html#doctype-legacy-string的问题Set HTML5 doctype with XSLT,其中说:

对于无法输出带有短 DOCTYPE“ <!DOCTYPE html>”的 HTML 标记的 HTML 生成器,可以将DOCTYPE 遗留字符串插入 DOCTYPE [...]

换句话说,<!DOCTYPE html SYSTEM "about:legacy-compat">or <!DOCTYPE html SYSTEM 'about:legacy-compat'>,不区分大小写,单引号或双引号中的部分除外。

导致这样一行Java代码:

trans.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "about:legacy-compat");
于 2014-05-21T19:48:48.370 回答
1

试试这里的建议https://stackoverflow.com/a/6637886/116509。基本上它看起来无法通过标准的 Java DOM 支持来完成。

你也可以试试 StAX

    XMLStreamWriter xmlStreamWriter =
        XMLOutputFactory.newFactory().createXMLStreamWriter( System.out, doc.getXmlEncoding() );
    Result result = new StAXResult( xmlStreamWriter );
    // ... create dtd String 
    xmlStreamWriter.writeDTD( dtd );
    DOMSource source = new DOMSource( doc );
    trans.transform( source, result );

但这很丑,因为 DTD 参数是 a String,而您只有一个DocumentType对象。

于 2012-05-25T08:16:07.250 回答