使用java中的SAX解析器从xml文件中提取xml节点(不是文本但是完整的xml)和其他测试节点

时间:2012-07-17 20:32:19

标签: java xml sax stax

我必须从每个范围大约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 Detail XML:

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


2)书:123
作者:梅森
PrintCompany Detail XML:

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


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

Sam 
  Laser
      Oreilly

确切的内容和空格。

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

1 个答案:

答案 0 :(得分:0)

我很想使用XOM来完成这类任务,而不是直接使用SAX或StAX。 XOM是一种类似于DOM或JDOM的基于树的表示,但它支持以一种半流方式处理XML“twigs”,非常适合您有许多类似元素可以独立处理的情况。另一个。此外,每个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内,您可以访问整个Book XML树作为XOM节点,但无需一次性将整个文件加载到内存中 - 两者都是最好的。 XOM tutorial的“工厂,过滤器,子类和流”部分提供了有关此技术的更多详细信息。

此示例仅显示XOM API的最基本位,但如果您需要执行更复杂的处理,它还提供强大的XPath支持。例如,您可以使用

直接访问PrintMachine中的processBook元素
Element machine = (Element)book.query("PrintingCompanyDT/PrintMachine").get(0);

或者如果结构不那么规律,例如PrintingCompanyDT有时是Book的直接孩子,有时甚至更深(例如孙子),那么你可以使用像

这样的查询
Element printingCompanyDT = (Element)book.query(".//PrintingCompanyDT").get(0);

//是用于在任何级别查找后代的XPath表示法,而不是仅查找直接子级的/