Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java org.w3c.dom.Document打印无效的XML文件_Java_Xml_Jsoup - Fatal编程技术网

Java org.w3c.dom.Document打印无效的XML文件

Java org.w3c.dom.Document打印无效的XML文件,java,xml,jsoup,Java,Xml,Jsoup,我有一个XMLorg.w3c.dom.Document,来自一个HTMLorg.jsoup.nodes.Document 当我序列化org.w3c.dom.Document时,它会生成一个无效的XML文件:它不会关闭META标记 为什么??这是虫子吗?从jsoup?从javaorg.w3c.dom?从javax.xml.transform.Transformer 相关错误: W3CDom.fromJsoup在定义xmlns时失败 org.jsoup.nodes.Document.toStrin

我有一个XML
org.w3c.dom.Document
,来自一个HTML
org.jsoup.nodes.Document

当我序列化
org.w3c.dom.Document
时,它会生成一个无效的XML文件:它不会关闭
META
标记

为什么??这是虫子吗?从
jsoup
?从java
org.w3c.dom
?从
javax.xml.transform.Transformer

相关错误:

  • W3CDom.fromJsoup在定义xmlns时失败
  • org.jsoup.nodes.Document.toString()是否应生成有效的XML文件
    
示例代码:

import org.jsoup.Jsoup;
import org.jsoup.helper.W3CDom;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;

public class Test130e {
    public static void main(String[] args) throws Exception {
        String html = "<html><head><script async src=\"http://example.com/script.js\"></script></head></html>";

        org.jsoup.nodes.Document jsoupDoc = Jsoup.parse(html); 
        System.out.println("+++ jsoupDoc.toString()");
        System.out.println(jsoupDoc.toString());


        Document w3cDoc = new W3CDom().fromJsoup(jsoupDoc);
        String xml = w3cDocToString(w3cDoc);

        System.out.println("+++ xml");
        System.out.println(xml);

        // this previous xml file is invalid, and so it fails to parse it
        // The element type "META" must be terminated by the matching end-tag "</META>".
        Document w3cDoc2 = parseXml(xml);
    }

    static Document parseXml(String content) throws Exception {
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        return documentBuilder.parse(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
    }

private static String w3cDocToString(Document w3cDoc) throws TransformerException {
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
    StreamResult result = new StreamResult(new StringWriter());
    DOMSource source = new DOMSource(w3cDoc);
    transformer.transform(source, result);
    return result.getWriter().toString();
}

}

为什么
w3cDocToString
构建一个无效的XML文件(它不会关闭
META
标记)


这是虫子吗?从
jsoup
?从java
org.w3c.dom

它在
org.w3c.dom
中不是一个bug,因为它不会呈现XML

DOM实现既不会忘记也不会记得关闭标记,因为它只是结构的内存表示(DOM中的OM代表对象模型)。模型可以转换为XML、JSON、ProtocolBuffers等,它们都有不同的编码。无论将其呈现为XML,都会“忘记”关闭标记

您正在使用
javax.xml.transform.Transformer
抽象类的实现将DOM转换为xml,但具体类未知/未指定。似乎这就是产生错误XML的原因。您可能需要打印出transformer.getClass()
以查看实际实现是什么:它取决于环境设置、类路径中的服务提供者等

警告:我以前从未听说过jsoup。

(澄清了我对评论的回答;评论与当前形式的答案不再相关)

在HTML中,
元素是自动关闭的;没有结束标记

您已经构建了一个DOM文档,它是一个节点树,其中最顶层的节点是一个HTML元素

然后使用JAXP序列化程序序列化DOM文档,而不指定输出方法。默认的输出方法取决于根元素,即HTML,因此您将获得HTML序列化。HTML序列化程序向输出中添加未关闭的元标记。

HTML!=XML 有效的XML,但无效的HTML:

<script src="jacoco-resources/sort.js" type="text/javascript"/>
<script src="jacoco-resources/sort.js" type="text/javascript"></script>          

我在本地电脑上运行了这个程序,得到了同样的结果。如果我通过终止标记来修改jsoup创建的XML,javax.XML.parsers.DocumentBuilder解析不会吐出鲜血。我同意这看起来像jsoup中的一个bug,因为它没有创建一个带有适当结尾标记的标记。这也许是你为开源社区做出贡献的机会。我刚刚去jsoup提交了一份bug报告,发现你已经击败了我。干得好:)您是否尝试过添加
transformer.setOutputProperty(OutputKeys.METHOD,“xml”)
你的transformer配置?@EricGreen,我已经为开源社区做了贡献。这是我在jsoup上的最后一次拉取请求:)@Alohci,很有趣!如果我添加这个,那么转换器的输出将丢弃META标记(它不在那里)。为什么?另外,如果我在这之前要求使用OutputKeys.METHOD,它会说它已经是“xml”。真奇怪!我已经相应地更新了这个问题。我正在将Jsoup文档转换为w3c文档,即XML。在XML中,元标记应该关闭。请再次阅读问题。
org.jsoup.helper.W3CDom
使用w3c
DocumentBuilder
及其
createElement
节点函数构造一个
org.w3c.dom.Document
;您不能“忘记”关闭标签;这是由
org.w3c.dom
完成的。因此,在我看来,
org.w3c.dom
中有一个bug,听起来很奇怪,或者在
Transformer
中有一个bug。同样,
org.jsoup.helper.W3CDom
正在使用
org.w3c.dom.Document
创建元素。在我看来,如果转换器没有关闭一个标记(从而生成一个无效的xml文件),那么那里就有一个bug(不在jsoup中)。我还在底部更新了一些信息,显示了
转换器的一个非常奇怪的行为。注意:
transformer
(呈现XML)不是来自jsoup,而是来自
javax.XML.transform
@DavidPortabella关于
javax.XML.transform
,我将更新我的答案。
<script src="jacoco-resources/sort.js" type="text/javascript"/>
<script src="jacoco-resources/sort.js" type="text/javascript"></script>          
        Document template = ....

        //So, we need to generate the HTML format! 
        Transformer t = TransformerFactory.newInstance().newTransformer();

        // for "XHTML" serialization, use the output method "xml"
        // and set publicId as shown
        t.setOutputProperty(OutputKeys.METHOD, "xml");

        t.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
                            "-//W3C//DTD XHTML 1.0 Transitional//EN");

        t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");

        // For "HTML" serialization, use
        t.setOutputProperty(OutputKeys.METHOD, "html");
        java.io.Writer writer = new java.io.FileWriter(path + "/code-coverage-total.html");
        // Serialize DOM tree
        t.transform(new DOMSource(template), new StreamResult(writer));