Daten in einer meta.xml einer OpenOffice-Datei ändern

anzy

Grünschnabel
Hallo,

ich hoffe irgendjemand dieser großen Forumgemeinde kann mir helfen. Ich habe schon sehr viel in Tutorien, Foren etc. gesucht, aber keine Lösung für mein Problem gefunden. Aber am besten beschreibe ich mal worum es geht:

Ich habe eine odt-Datei (ist in ihrem Kern ein Zip-Verzeichnis), die mit OpenOffice erstellt wurde. In diesem Verzeichnis befindet sich unter anderem eine meta.xml. In dieser möchte ich nun die Dokument-Eigenschaften (also Autor, Titel, Beschreibung etc.) ändern.

Meine Idee war die odt-Datei erstmal in ein entpacktes Zip-Verzeichnis umzuwandeln, dann die meta.xml auszulesen, zu ändern und zurückzuschreiben und dann das Verzeichnis wieder zusammenzupacken und ganz am Ende noch in eine odt umzubenennen. Das erwieß sich jedoch als sehr umständlich und scheiterte am ändern und zurückschreiben der meta.xml. Noch eine Schwierigkeit erschwert das ganze zusätzlich: Es sollte keine Instanz von OpenOffice gebraucht werden und auch das Dokument soll nicht geöffnet werden. Damit dürften UNO und NOA tabu sein...

Hat jemand eine Idee wie das möglichst einfach zu realisieren ist?

Danke schon mal im Vorraus für eure Hilfe. Grüsse
Anzy
 
Hallo,

In dem Beispiel ändere ich mal den Text des Dublin Core Creator Elements (dc:creator) programatisch... hätte man aber auch genau so gut über ein entsprechendes XSLT Stylesheet machen können).

Das Zurückschreiben des Ergebnisses ist jedoch etwas komplizierter... zuerst kopiere ich die nicht manipulierten Elemente in ein temporäres ZipArchiv und anschließend schreibe ich die Manipulierten Elemente rein. Danach benenne ich die temporäre Datei in die ursprüngliche Datei um.

Schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 * @author Tom
 */
public class OpenOfficeDocumentPatcher {

  /**
   * @param args
   */
  public static void main(String[] args) throws Exception {
    File originalOdtFile = new File("c:/bubu.odt");
    ZipFile odtFile = new ZipFile(originalOdtFile);

    String metaFileName = "meta.xml";
    ZipEntry metaZipEntry = odtFile.getEntry(metaFileName);

    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
      odtFile.getInputStream(metaZipEntry));
    Node dcCreatorNode = document.getElementsByTagName("dc:creator").item(0);
    System.out.println(dcCreatorNode.getTextContent());
    dcCreatorNode.setTextContent("Thomas Darimont");
    System.out.println(dcCreatorNode.getTextContent());

    File tempFile = File.createTempFile(originalOdtFile.getName(), "tmp");
    ZipOutputStream zipOutputStream = copyContentsToTempZipFile(odtFile, tempFile, metaFileName);
    odtFile.close();
    String originalFileName = originalOdtFile.getName();

    ZipEntry manipulatedMetaFileZipEntry = new ZipEntry(metaFileName);
    zipOutputStream.putNextEntry(manipulatedMetaFileZipEntry);
    TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document),
      new StreamResult(zipOutputStream));
    zipOutputStream.closeEntry();
    zipOutputStream.close();

    String originalOdtParentFilePath = originalOdtFile.getParent();
    originalOdtFile.renameTo(new File(originalOdtFile.getParent(), "old_" + originalFileName));
    tempFile.renameTo(new File(originalOdtParentFilePath, originalFileName));
  }


  private static ZipOutputStream copyContentsToTempZipFile(ZipFile odtFile, File tempFile,
    String exceptionalFileName) throws Exception {
    ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(tempFile));
    Enumeration<? extends ZipEntry> zipEntries = odtFile.entries();
    while (zipEntries.hasMoreElements()) {
      ZipEntry currentEntry = zipEntries.nextElement();

      if (exceptionalFileName.equals(currentEntry.getName())) {
        // skip exceptional files...
        continue;
      }
      ZipEntry newZipEntry = new ZipEntry(currentEntry.getName());
      zipOutputStream.putNextEntry(newZipEntry);
      InputStream inputStream = odtFile.getInputStream(currentEntry);
      byte[] buffer = new byte[16384];
      for (int bytesRead = inputStream.read(buffer); bytesRead > 0; bytesRead = inputStream.read(buffer)) {
        zipOutputStream.write(buffer, 0, bytesRead);
      }
      zipOutputStream.closeEntry();
    }
    return zipOutputStream;
  }
}

Gruß Tom
 
Hallo Tom,

vielen Dank für deine umfassende Antwort. Das hat mir wirklich sehr geholfen und ist auch viel einfacher als die von mir ausgedachte Vorgehensweise...

Der Tip mit den Dublin Core Elementen war Gold wert. Nachdem ich danach gegoogelt hatte, konnte ich auch alle anderen Meta-Daten wie gewünscht ändern.

Vielen Dank nochmals. :)

Grüsse
Anzy

Falls jemand anderes mal dieses Problem hat: http://dublincore.org/documents/dcmi-terms/
Da stehen alle Dublin Core Elemente drin und sind auch gut beschrieben.
 
Zurück