0

我必须从每个范围约 500MB 的大型 xml 文件中读取。批处理通常在每次运行中处理 500 个此类文件。我必须从中提取文本节点,同时从中提取 xml 节点。我在 java 中使用了 xpath DOM 以便于使用,但是由于内存问题,由于我的资源有限,这不起作用。

我现在打算在 java 中使用 SAX 或 stax - 可以轻松提取文本节点,但我不知道如何使用 sax 从 xml 中提取 xml 节点。

一个样品:

<?xml version="1.0"?>
<Library>
  <Book name = "ABC">
    <Author>John</Author>
    <PrintingCompanyDT><Printer>Sam</Printer><Printmachine>Laser</Printmachine>    
    <AssocPrint>Oreilly</AssocPrint> </PrintingCompanyDT>
  </Book>
  <Book name = "123">
    <Author>Mason</Author>
    <PrintingCompanyDTv<Printervkelly</Printer><Printmachine>DOTPrint</Printmachine>
    <AssocPrint>Oxford</AssocPrint> </PrintingCompanyDT>
  </Book>
</Library>

预期结果:1)书籍:ABC:
作者:John
PrintCompany 详细 XML:

<PrintingCompanyDT>
  <Printer>Sam</Printer>
  <Printmachine>Laser</Printmachine>
  <AssocPrint>Oreilly</AssocPrint> 
</PrintingCompanyDT>


2) 书籍:123
作者:Mason
PrintCompany 详细 XML:

<PrintingCompanyDT>
  <Printer>kelly</Printer>
  <Printmachine>DOTPrint</Printmachine>
  <AssocPrint>Oxford</AssocPrint>
</PrintingCompanyDT>


如果我尝试以常规方式在 public void characters(char ch[], int start, int length) 方法中附加字符,我会得到以下
1)Book: ABC:
Author:John
PrintCompany Detail XML:

Sam 
  Laser
      Oreilly

正是内容和空间。

有人可以建议如何通过 Java 中的 SAX 或 StaX 解析器从 xml 文件中提取 xml 节点。

4

1 回答 1

0

我很想将XOM用于此类任务,而不是直接使用 SAX 或 StAX。XOM 是一种类似于 DOM 或 JDOM 的基于树的表示,但它支持以一种半流式方式处理 XML“树枝”,非常适合您有许多可以独立处理的类似元素的情况其他。每个Node人都有一个toXML将节点打印为 XML 的方法。

import nu.xom.*;

public class LibraryProcessor extends NodeFactory {
  private Nodes empty = new Nodes();
  private bookNum = 0;

  /** Called for each closing tag in the XML */
  public Nodes finishMakingElement(Element element) {
    if("Book".equals(element.getLocalName())) {
      bookNum++;
      // process the complete Book element ...
      processBook(element);
      // ... and throw it away
      return empty;
    } else {
      // process other elements (except Book) in the normal way
      return super.finishMakingElement(element);
    }
  }

  private void processBook(Element book) {
    System.out.println(bookNum + ": " +
        book.getAttributeValue("name"));
    System.out.println("Author: " +
        book.getFirstChildElement("Author").getValue());
    System.out.println("PrintCompany Detail XML: " +
        book.getFirstChildElement("PrintingCompanyDT").toXML());
  }

  public static void main(String[] args) throws Exception {
    Builder builder = new Builder(new LibraryProcessor());
    builder.build(new File(args[0]));
  }
}

这将通过 XML 文档进行,依次processBook为每个元素调用一次。Book在其中processBook,您可以将整个BookXML 树作为 XOM 节点访问,但不必一次性将整个文件加载到内存中 - 两全其美。XOM 教程的“工厂、过滤器、子类化和流式处理”部分提供了有关此技术的更多详细信息。

此示例仅显示 XOM API 的最基本部分,但如果您需要进行更复杂的处理,它还提供了强大的 XPath 支持。例如,您可以直接访问using中的PrintMachine元素processBook

Element machine = (Element)book.query("PrintingCompanyDT/PrintMachine").get(0);

或者如果结构不是那么规则,例如,如果PrintingCompanyDT有时是直接孩子,Book有时是更深的(例如孙子),那么您可以使用类似的查询

Element printingCompanyDT = (Element)book.query(".//PrintingCompanyDT").get(0);

//作为在任何级别查找后代的 XPath 表示法,而不是/仅查找直接子代的 XPath 表示法)。

于 2012-07-17T22:53:32.487 回答