2011-06-24 31 views
0

使用StAX我有以下形式的200 MB的xml:代碼在Java

 <school name = "some school"> 
     <class standard = "2A"> 
      <student> 
      ..... 
      </student> 
      <student> 
      ..... 
      </student> 
      <student> 
      ..... 
      </student> 
     </class> 
     </school> 

我需要這個XML分割成幾個文件使用StAX這種n個學生在每個XML文件來,並且其結構被保存爲<school>,然後<class><students>。學校和班級的屬性也必須保留在最終的xml中。

這裏是我使用的代碼:

XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 

    String xmlFile = "input.XML"; 
    XMLEventReader reader = inputFactory.createXMLEventReader(new FileReader(xmlFile)); 

    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); 
    outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE); 

    XMLEventWriter writer = null; 

    int count = 0; 

    QName name = new QName(null, "student"); 

    try { 
     while (true) { 
      XMLEvent event = reader.nextEvent(); 
      if (event.isStartElement()) { 
       StartElement element = event.asStartElement(); 
       if (element.getName().equals(name)) { 
        String filename = "input"+ count + ".xml"; 
        writer = outputFactory.createXMLEventWriter(new FileWriter(filename)); 
        writeToFile(reader, event, writer); 
        writer.close(); 
        count++; 
       } 
      } 
      if (event.isEndDocument()) 
       break; 
     } 
    } catch (XMLStreamException e) { 
     throw e; 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     reader.close(); 
    } 

private static void writeToFile(XMLEventReader reader, XMLEvent startEvent, XMLEventWriter writer) throws XMLStreamException, IOException { 

    StartElement element = startEvent.asStartElement(); 
    QName name = element.getName(); 
    int stack = 1; 

    writer.add(element); 

    while (true) { 
     XMLEvent event = reader.nextEvent(); 
     if (event.isStartElement() && event.asStartElement().getName().equals(name)) 
      stack++; 
     if (event.isEndElement()) { 
      EndElement end = event.asEndElement(); 
      if (end.getName().equals(name)) { 
       stack--; 
       if (stack == 0) { 
        writer.add(event); 
        break; 
       } 
      } 
     } 
     writer.add(event); 
    } 

} 

請檢查函數調用writeToFile(reader, event, writer) try塊。這裏讀者對象只有student標籤。我需要的讀者有school,class,然後在其中有students。因此生成的文件與原始文件具有相似的結構,但每個文件只有較少的子文件。

在此先感謝。

+4

這不是一個代碼生成服務。嘗試一下(使用你找到的樣本),並在遇到問題時發佈**具體**問題。 –

+3

然後**發佈**你試圖和**解釋**你卡在哪裏。我**願意幫忙,但我不想成爲一個代碼生成服務(我不希望這個網站成爲一個)。 –

+2

請不要以約260倍的聲譽譴責用戶。 – musiKk

回答

0

你有代碼來確定何時開始一個新的文件,我沒有仔細檢查,但完成一個文件,並開始下一個進程肯定是不完整的。

在達到您想要結束文件的點時,您必須在關閉文件之前爲封閉的<class><school>標籤生成結束事件。當你開始你的新文件時,你需要在打開新文件之後以及在再次開始複製學生事件之前爲其生成啓動事件。

爲了正確生成啓動事件,您必須保留輸入中的相應事件。

0

節省您自己的麻煩和時間,並使用您當前擁有的扁平xml文件結構,然後創建POJO對象,它將表示每個對象,如您所述; 學生,學校。然後使用Jaxb將結構中不同部分的對象綁定在一起。然後,您可以有效地解組XML,並像訪問SQL對象一樣訪問各種元素。

使用此鏈接爲起點XML parsing with JAXB

一個問題做這種方式是內存消耗。爲了設計靈活性和內存管理,我會建議使用SQL來處理這個問題。

+2

問題是XML是200MB,如果使用JAXB可能會耗盡內存將整個XML解析到對象樹中。 – Alvin

+0

@Alvin 200mb是一個安靜的大文件 - 但我認爲通過分裂根文件的設計方法不會解決他的內存管理問題,甚至是靈活性問題。如果學生文件增長到200Mb,該怎麼辦?那麼另一個例程將它分裂? – Bitmap

+0

我的問題正是你懷疑的。如果任何文件增長超過一定大小,它將被再次分解。 – Anand

0

我想你可以在「學生」開始元素事件之前跟蹤父事件的列表,並將它傳遞給writeToFile()方法。然後在writeToFile()方法中,您可以使用該列表來模擬「學校」和「班級」事件。