2013-05-10 28 views
7

Tôi có một XML rất lớn (~ 2GB) và tôi cần phải thêm các yếu tố mới và sửa đổi các yếu tố cũ. Ví dụ, tôi có:Làm thế nào để sửa đổi một tệp XML khổng lồ của StAX?

<books> 
    <book>....</book> 
    ... 
    <book>....</book> 
</books> 

Và muốn có được:

<books> 
    <book> 
     <index></index> 
     .... 
    </book> 
    ... 
    <book> 
     <index></index> 
     .... 
    </book> 
</books> 

tôi đã sử dụng đoạn mã sau:

XMLInputFactory inFactory = XMLInputFactory.newInstance(); 
XMLEventReader eventReader = inFactory.createXMLEventReader(new FileInputStream(file)); 
XMLOutputFactory factory = XMLOutputFactory.newInstance(); 
XMLStreamWriter writer = factory.createXMLStreamWriter(new FileWriter(file, true)); 
while (eventReader.hasNext()) { 
    XMLEvent event = eventReader.nextEvent(); 
    if (event.getEventType() == XMLEvent.START_ELEMENT) { 
     if (event.asStartElement().getName().toString().equalsIgnoreCase("book")) { 
      writer.writeStartElement("index"); 
      writer.writeEndElement(); 
     } 
    } 
} 
writer.close(); 

Nhưng kết quả là như sau:

<books> 
    <book>....</book> 
    .... 
    <book>....</book> 
</books><index></index> 

Bất kỳ ý tưởng nào?

+0

Nếu bạn có đủ bộ nhớ, vtd-xml là tùy chọn cung cấp mã hóa đơn giản hơn đáng kể ... trong khi đó mất thêm 50% bộ nhớ và giữ tất cả mọi thứ trong bộ nhớ, nó không phát sinh như DOM http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf –

Trả lời

17

Hãy thử điều này

XMLInputFactory inFactory = XMLInputFactory.newInstance(); 
    XMLEventReader eventReader = inFactory.createXMLEventReader(new FileInputStream("1.xml")); 
    XMLOutputFactory factory = XMLOutputFactory.newInstance(); 
    XMLEventWriter writer = factory.createXMLEventWriter(new FileWriter(file)); 
    XMLEventFactory eventFactory = XMLEventFactory.newInstance(); 
    while (eventReader.hasNext()) { 
     XMLEvent event = eventReader.nextEvent(); 
     writer.add(event); 
     if (event.getEventType() == XMLEvent.START_ELEMENT) { 
      if (event.asStartElement().getName().toString().equalsIgnoreCase("book")) { 
       writer.add(eventFactory.createStartElement("", null, "index")); 
       writer.add(eventFactory.createEndElement("", null, "index")); 
      } 
     } 
    } 
    writer.close(); 

Ghi chú

mới FileWriter (file, true) được phụ thêm vào cuối của tập tin, bạn hầu như không thực sự cần nó

equalsIgnoreCase ("sách") là ý tưởng tồi vì XML phân biệt chữ hoa chữ thường

+0

Thật không may, mã này không hoạt động. NetBeans cho tôi một lỗi: 'Gây ra bởi: javax.xml.stream.XMLStreamException: ParseError tại [hàng, col]: [4,2] Thông báo: Cấu trúc tài liệu XML phải bắt đầu và kết thúc trong cùng một thực thể. \t tại com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next (XMLStreamReaderImpl.java target="98) \t tại com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent (XMLEventReaderImpl.java:83) \t tại librarian.controllers.BookCardController.saveToXML (BookCardController.java:140) \t ... 54 thêm ' Và hơn nữa nó xóa tất cả nội dung của tệp ... – Eugene

+0

ngoại lệ là gì? Tôi đã thử nghiệm nó với xml của bạn trước khi đăng –

+0

Vừa thử nó. Và một lần nữa ngoại lệ tương tự: 'Gây ra bởi: javax.xml.stream.XMLStreamException: ParseError tại [hàng, col]: [3,5] Thông báo: Cấu trúc tài liệu XML phải bắt đầu và kết thúc trong cùng một thực thể. \t tại com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next (XMLStreamReaderImpl.java target="98) \t tại com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent (XMLEventReaderImpl.java:83) \t tại librarian.controllers.BookCardController.saveToXML (BookCardController.java:138) \t ... 54 thêm ' Tôi thực sự không biết tại sao, nhưng mã bổ sung này xóa tệp của tôi. – Eugene

3

Vâng, điều này khá rõ ràng lý do tại sao nó hoạt động theo cách của nó. Những gì bạn đang thực sự làm là mở tệp hiện có trong chế độ nối thêm đầu ra và viết phần tử ở cuối. Điều đó rõ ràng mâu thuẫn với những gì bạn đang cố gắng làm.

(Ngoài ra: Tôi ngạc nhiên rằng nó hoạt động cũng như nó cho rằng phía đầu vào có khả năng thấy các phần tử mà bên đầu ra được thêm vào cuối tệp. Và thực sự là các ngoại lệ như Evgeniy Dorofeev's Vấn đề là nếu bạn cố gắng đọc và viết một tập tin văn bản cùng một lúc, và người đọc hoặc nhà văn sử dụng bất kỳ hình thức đệm, rõ ràng hoặc ngầm, người đọc là chịu trách nhiệm xem các trạng thái một phần.)

Để khắc phục điều này, bạn phải bắt đầu bằng cách đọc từ một tệp và ghi vào một tệp khác. Phụ thêm sẽ không hoạt động. Sau đó, bạn phải sắp xếp các phần tử, thuộc tính, nội dung, vv được đọc từ tệp đầu vào được sao chép vào tệp đầu ra. Cuối cùng, bạn cần phải thêm các yếu tố bổ sung tại các điểm thích hợp.


And is there any possibility to open the XML file in mode like RandomAccessFile, but write in it by StAX methods?

số Đó là về mặt lý thuyết là không thể. Để có thể điều hướng xung quanh cấu trúc của tệp XML trong một tệp "ngẫu nhiên", trước tiên bạn cần phải phân tích cú pháp toàn bộ nội dung và xây dựng chỉ mục về tất cả các phần tử. Ngay cả khi bạn đã thực hiện điều đó, XML vẫn được lưu trữ dưới dạng các ký tự trong một tệp và truy cập ngẫu nhiên không cho phép bạn chèn và xóa các ký tự ở giữa tệp.

Có thể đặt cược tốt nhất của bạn sẽ kết hợp XSL và trình phân tích cú pháp kiểu SAX; ví dụ. một cái gì đó dọc theo dòng của bài viết này của IBM: http://ibm.com/developerworks/xml/library/x-tiptrax

+0

Và có khả năng nào để mở tệp XML không ở chế độ như RandomAccessFile, nhưng viết bằng phương pháp StAX? – Eugene

+0

Về mặt lý thuyết có thể ... tôi đoán ... nhưng tôi không biết về bất kỳ giải pháp nào có sẵn, đó là những gì bạn muốn. –

Các vấn đề liên quan