【问题标题】:How do you format a huge XML file in Java?如何在 Java 中格式化一个巨大的 XML 文件?
【发布时间】:2011-12-05 22:42:36
【问题描述】:

我必须使用 Java 处理一个 4GB 的 XML 文件。

我的问题是提供的 XML 文件未格式化,内容实际上都在一行上,没有换行符。

我想格式化 XML 文件,使其具有合理的换行和缩进,这样如果验证失败(我使用 JAXB 进行解析),我可以轻松定位和检查 XML 的有问题的部分。

有谁知道可以在 Java 中以编程方式应用一些基本 XML 格式的框架?

【问题讨论】:

  • 您可能会问自己,以编程方式格式化 4 gig XML 文件是否有意义。如果验证失败只是偶尔发生一次,我只需使用 xmllint 之类的外部工具对其进行格式化,然后以编程方式读取它,然后找出问题所在。
  • 为什么不能像格式化小文件一样格式化它?

标签: java xml jaxb


【解决方案1】:

CkXml 将通过getXml 方法为您提供所需的内容。

CkXml xml = new CkXml();
xml.LoadXml("<root><company><name>Chilkat Software, Inc.</name><url>http://www.chilkatsoft.com/</url><phone>630-784-9670</phone></company></root>");
xml.getXml();

// Output looks like this:
// 
// <?xml version="1.0" encoding="utf-8" ?>
// 
// <root>
//     <company>
//         <name>Chilkat Software, Inc.</name>
//         <url>http://www.chilkatsoft.com/</url>
//         <phone>630-784-9670</phone>
//     </company>
// </root>

还有 JTidy 是针对 HTML 的,但应该足够好满足你的需要。

【讨论】:

    【解决方案2】:

    不确定,但是JTidy 呢?

    【讨论】:

      【解决方案3】:

      我会考虑使用Transformer。大致如下:

      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      StreamResult tranformedDoc = new StreamResult(new StringWriter());
      DOMSource source = new DOMSource(new Document()); // Insert content here.
      
      transformer.transform(source, transformedDoc);
      
      // Output string to byte array
      return transformedDoc.getWriter().toString().getBytes();
      

      鉴于您的 XML 的大小,我不知道这对您来说是否是一个好的解决方案,但这是一个起点。也可能还有更有效的方法可以做到这一点,因此会受到批评。

      【讨论】:

        【解决方案4】:

        您可以使用 JAXP 身份转换,如下所示:

        javax.xml.transform.Source xmlSource = 
            new javax.xml.transform.stream.StreamSource(xmlFile);
        javax.xml.transform.Result result = 
            new javax.xml.transform.stream.StreamResult(System.out);
        javax.xml.transform.TransformerFactory transFact = 
            javax.xml.transform.TransformerFactory.newInstance();
        javax.xml.transform.Transformer trans = 
            transFact.newTransformer();
        trans.setOutputProperty("indent", "yes")
        trans.transform(xmlSource, result);
        

        如果幸运的话,这将是一个流式转换(如果 TransformerFactory 是 Saxon,它肯定会)。

        您可以扩展此方法以将流式验证步骤插入到管道中,从而避免对数据进行两次传递。如果您在 Saxon 中全部执行此操作,那么额外的好处是缩进将是模式敏感的 - 确保缩进永远不会干扰模式有效性。

        但是,尽管这符合规定的要求,但我不确定它是否能实现基本目标。缩进是为了使数据可读。您是否考虑过将使用哪些工具来显示和手动编辑 4GB 文档?我想不出任何可以完成这项工作的东西,而且可用性会很糟糕。此外,4Gb 文档很可能是机器生成的,因此如果它无效,您需要修复生成它的程序,而不是数据本身 - 数据中的任何错误都可能会系统地重复多次。

        【讨论】:

          【解决方案5】:

          我假设 XML 格式正确,只是无效。如果您自己通过 JAXB 生成 XML,则可以在编组对象时输出人类可读的 XML。您的Marshaller 需要提供格式化输出选项。您可以这样设置属性:

          marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
          

          如果文档是提供给您的(并且您没有生成它),那么像UltraEdit 这样的工具可能最容易使用。它处理大型文档和格式/编辑 XML。有免费试用,所以如果这是一个短期的开发问题,也许您可​​以在试用期内解决它。

          【讨论】:

            【解决方案6】:

            设置一个 sax 解析器 http://docs.oracle.com/javase/6/docs/api/javax/xml/parsers/SAXParser.html

            创建您自己的内容处理程序并将其分配给 sax 解析器:

            saxParser.getXmlReader().setContentHandler(new MyContentHandler());
            

            ContentHandler 提供对解析的所有方面的访问,并且如果它具有不同的子部分,您可以分段处理 xml,例如:

            <doc>
               <app></app>
               <app></app>
            </doc>
            

            您可以一次解组一个“应用程序”并在尝试下一个应用程序之前对其进行处理。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-11-01
              • 2011-02-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-07
              • 2013-05-04
              • 1970-01-01
              相关资源
              最近更新 更多