草庐IT

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

coder 2024-07-01 原文

我有一个 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?

相关错误:

示例代码:

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

}

输出:

+++ jsoupDoc.toString()
<html>
 <head>
  <script async src="http://example.com/script.js"></script>
 </head>
 <body></body>
</html>

+++ xml
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script async="" src="http://example.com/script.js"></script>
</head>
<body></body>
</html>

[Fatal Error] :5:3: The element type "META" must be terminated by the matching end-tag "</META>".
Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 3; The element type "META" must be terminated by the matching end-tag "</META>".
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:121)
    at playground.Test130e.parseXml(Test130.java:116)
    at playground.Test130e.main(Test130.java:110)

为什么 w3cDocToString 构建了一个无效的 XML 文件(它没有关闭 META 标签)?

这是一个错误吗?来自 jsoup?来自 java org.w3c.dom?


更新

关于@Alohci 的评论:

Have you tried adding transformer.setOutputProperty(OutputKeys.METHOD, "xml"); to your transformer configuration?

有趣! 如果我添加这个,那么转换器的输出会丢弃 META 标签(它不存在)。为什么?

此外,如果我在此之前添加以下行,它表示它已经是“xml”。太奇怪了!

System.out.println(transformer.getOutputProperty(OutputKeys.METHOD));

为什么 w3cDocToString 构建了一个无效的 XML 文件(它没有关闭 META 标签)?

这是一个错误吗?来自 jsoup?来自 java org.w3c.dom?

最佳答案

这不是 org.w3c.dom 中的错误,因为它没有呈现 XML。

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

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

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

关于java - org.w3c.dom.Document 打印无效的 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51387871/

有关java - org.w3c.dom.Document 打印无效的 XML 文件的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  5. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  6. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  9. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  10. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

随机推荐