2013-02-21 3 views
1

Когда я сохранить DOCX файл после обработки какого-либо текста с XPath с помощью POI, я затем передать ByteArrayOutputStream нового ByteArrayInputStream и кормить его dox4j сdocx4j не может прочитать POI сохраненные файлы, кто виноват?

wordMLPackage = WordprocessingMLPackage.load(
    bis 
); 

С 3 из 4 моих шаблонов это бросает исключение:

org.docx4j.openpackaging.exceptions.InvalidFormatException: Unexpected package (docx4j supports docx/docxm and pptx only 
    at org.docx4j.openpackaging.contenttype.ContentTypeManager.createPackage(ContentTypeManager.java:834) 

код выглядит примерно так:

/* Return a package of the appropriate type. Used when loading an existing 
* Package, with an already populated [Content_Types].xml. When 
* creating a new Package, start with the new WordprocessingMLPackage constructor. */ 
public OpcPackage createPackage() throws InvalidFormatException { 

    /* 
    * How do we know what type of Package this is? 
    * 
    * In principle, either: 
    * 
    * 1. We were told its file extension or mime type in the 
    * constructor/method parameters, or 
    * 
    * 2. Because [Content_Types].xml contains an override for PartName 
    * /document.xml of content type 
    * application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml 
    * 
    * The latter approach is more reliable, so .. 
    * 
    */ 
    OpcPackage p; 

    if (getPartNameOverridenByContentType(ContentTypes.WORDPROCESSINGML_DOCUMENT) != null 
      || getPartNameOverridenByContentType(ContentTypes.WORDPROCESSINGML_DOCUMENT_MACROENABLED) != null 
      || getPartNameOverridenByContentType(ContentTypes.WORDPROCESSINGML_TEMPLATE) != null 
      || getPartNameOverridenByContentType(ContentTypes.WORDPROCESSINGML_TEMPLATE_MACROENABLED) != null) { 
     log.info("Detected WordProcessingML package "); 
     p = new WordprocessingMLPackage(this); 
     return p; 
    } else if (getPartNameOverridenByContentType(ContentTypes.PRESENTATIONML_MAIN) != null 
      || getPartNameOverridenByContentType(ContentTypes.PRESENTATIONML_TEMPLATE) != null 
      || getPartNameOverridenByContentType(ContentTypes.PRESENTATIONML_SLIDESHOW) != null) { 
     log.info("Detected PresentationMLPackage package "); 
     p = new PresentationMLPackage(this); 
     return p; 
    } else if (getPartNameOverridenByContentType(ContentTypes.SPREADSHEETML_WORKBOOK) != null 
      || getPartNameOverridenByContentType(ContentTypes.SPREADSHEETML_WORKBOOK_MACROENABLED) != null 
      || getPartNameOverridenByContentType(ContentTypes.SPREADSHEETML_TEMPLATE) != null 
      || getPartNameOverridenByContentType(ContentTypes.SPREADSHEETML_TEMPLATE_MACROENABLED) != null) { 
     // "xlam", "xlsb" ? 
     log.info("Detected SpreadhseetMLPackage package "); 
     p = new SpreadsheetMLPackage(this); 
     return p; 

    } else if (getPartNameOverridenByContentType(ContentTypes.DRAWINGML_DIAGRAM_LAYOUT) != null) { 
     log.info("Detected Glox file "); 
     p = new GloxPackage(this); 
     return p; 
    } else { 
     throw new InvalidFormatException("Unexpected package (docx4j supports docx/docxm and pptx only"); 
     //return new Package(this); 
    } 
} 

это, кажется, не в состоянии соответствовать переопределение определенного типа содержимого. В своих исходных шаблонов DOCX есть [Content_Types] .xml файл, который имеет:

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> 
    <Override PartName="/_rels/.rels"  ContentType="application/vnd.openxmlformats-package.relationships+xml" /> 
    <Override PartName="/word/fontTable.xml"  ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" /> 
    <Override PartName="/word/_rels/document.xml.rels"  ContentType="application/vnd.openxmlformats-package.relationships+xml" /> 
    <Override PartName="/word/media/image1.wmf"   ContentType="image/x-wmf" /> 
    <Override PartName="/word/comments.xml"   ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" /> 
    <Override PartName="/word/numbering.xml"  ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" /> 
    <Override PartName="/word/footer1.xml"  ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" /> 
    <Override PartName="/word/document.xml"   ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" /> 
    <Override PartName="/word/styles.xml"  ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" /> 
    <Override PartName="/docProps/app.xml"  ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" /> 
    <Override PartName="/docProps/core.xml"   ContentType="application/vnd.openxmlformats-package.core-properties+xml" /> 
</Types> 

После обработки с POI .xml в [Content_Types] выглядит следующим образом:

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> 
    <Default Extension="xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/> 
    <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> 
    <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/> 
    <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/> 
    <Override PartName="/word/_rels/document.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> 
    <Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"/> 
    <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/> 
    <Override PartName="/word/footer1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"/> 
    <Override PartName="/word/media/image1.wmf" ContentType="image/x-wmf"/> 
    <Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/> 
    <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/> 
</Types> 

Обратите внимание, что для Override PartName = "/ word/document.xml" отсутствует!

Является ли это допустимым файлом типа содержимого файла без переопределения слова/document.xml? Он открывается в LibreOffice без жалоб. Является ли docx4j полагаться на теги Override, которые могут отсутствовать в типах контента, или POI неправильно записывает типы контента для некоторых моих файлов (3 из 4).

+1

Я думаю, что это ошибка docx4j. POI устанавливает значение по умолчанию с правильным типом, который docx4j выглядит игнорирующим. – Gagravarr

+0

Я согласен, я открыл проблему 46 в проекте github с некоторыми идеями кода, чтобы исправить это. Мне все еще интересно, что говорит спецификация в отношении меток Override. – chugadie

ответ

2

Раскрытие: Я docx4j проект ведет

Что POI делают, кажется законными согласно спецификации, но не идеально.

В соответствии с ECMA-376 Часть 2, «Получение типа содержимого детали», docx4j должен найти тип содержимого документа docx, если он указан так, как это делает POI.

WordprocessingML глава в Части 1, говорится в разделе «Пакет Структура»:

Во-первых, тип контента для отношений частей и основного документа часть (только необходимая часть) должна быть определена (физически расположенный в /[Content_Types].xml в упаковке):

<Types 
xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> 
&lt;Default Extension="rels" 
ContentType="application/vnd.openxmlformatspackage. 
relationships+xml"/> 
<Override PartName="/document.xml" 
ContentType="application/vnd.openxmlformatsofficedocument. 
wordprocessingml.document.main+xml"/> </Types> 

Мое чтение этого является то, что вы должны определить тип содержимого основной части документа (который POI лань s), и только намек - это использовать переопределение для этого.

Для меня не имеет смысла использовать ваш .xml по умолчанию для того, что будет соответствовать одному (или, возможно, 2 или 3 частям), когда большинство частей являются .xml и потребует переопределения для указания чего-либо другой. Интересно, почему POI сделала это так, что отличается от предложения в спецификации и отличается от того, что издает Word.

Сказанное, https://github.com/plutext/docx4j/commit/1c1190fc3a2fc6e191c825a0e30fde2654cc997c должно исправить это.

 Смежные вопросы

  • Нет связанных вопросов^_^