Java XML Prettyprinting包含DTD注释?

时间:2018-02-06 11:22:30

标签: java xml-parsing dtd xalan

使用内置Java(使用jdk 8u151和8u161测试)XML处理引擎解析XML数据时,我得到了奇怪的结果。如果我在DTD中使用参数化实体参数,则所有跟随来自DTD的SGML注释最终会出现在输出文档中。

这是我正在运行的(最小)代码:

import java.io.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.InputSource;

public class FormatBug {

    public static void main( String[] args ) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        Reader in = new FileReader( args[0] );
        Writer out = new FileWriter( args[1] );
        t.transform( new SAXSource( new InputSource(in) ), new StreamResult(out) );
        out.flush();
        out.close();
    }
}

源文档如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE doc SYSTEM "doc.dtd">
<doc><p>This is a <b>bold</b> line.</p></doc>

DTD(doc.dtd)如下所示:

<!ELEMENT doc (p+)>
<!ENTITY % floats "b" >
<!-- comment before -->
<!ELEMENT p ( #PCDATA | %floats; )*>
<!-- comment after -->
<!ELEMENT b (#PCDATA)>

结果如下:

<!-- comment after --><!DOCTYPE doc SYSTEM "doc.dtd">
<doc><p>This is a <b>bold</b> line.</p></doc>

将p的规则替换为

<!ELEMENT p ( #PCDATA | b )*>

虚假评论消失了。

有人能解释一下这里发生了什么吗?

我还检查了JDK 9.0.4,其中所有注释正在被复制,所以我认为我可能做了一些完全错误的事情。

1 个答案:

答案 0 :(得分:0)

我可以在JDK 1.8.0_151上确认这一点,并认为由于使用SAXSource作为转换的输入源而导致问题,因为Java's javax.xml.parsers.SAXParser ignores comments

使用StAX的以下变体不会在JDK 1.8上打印虚假注释,因此可能有助于实现在JDK 1.8和1.9上运行统一Java源:

import java.io.*;
import javax.xml.stream.*;
import javax.xml.transform.*;
import javax.xml.transform.stax.*;
import javax.xml.transform.stream.*;

public class FormatBugUsingStaX {

    public static void main(String[] args) throws Exception {

        InputStream inputStream = new FileInputStream(args[0]);
        InputStreamReader in = new InputStreamReader(inputStream);
        XMLInputFactory factory = XMLInputFactory.newInstance();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        XMLStreamReader streamReader = factory.createXMLStreamReader(in);
        Writer out = new FileWriter(args[1]);
        t.transform(new StAXSource(streamReader), new StreamResult(out));
    }
}

编辑:如果您打算继续发表评论,那么您可以通过使用其他StAX实施获得好运;比照Transforming a StAX Source in Java