2013-02-12 2 views
0

Я пытаюсь создать прототип для преобразования PDF-файла в файл XML. Результат немного странный, все символы становятся символами. Я думаю, что ошибка там, где StringBuffer берет данные из массива байтов. Может кто-нибудь с знаниями Java, пожалуйста, помогите?Использование Java для преобразования PDF в XML

Это прототип программного обеспечения использует API iText. Чтобы прочитать файл PDF, мы использовали класс PDFReader. Данные сначала преобразуются в массив байтов, затем с использованием Stringbuffer, он снова преобразуется в строку. Затем мы использовали StreamResult, который выступает в качестве держателя для преобразованного результата в XML.

После этого класс Transformer обрабатывает XML из множества источников и записывает вывод преобразования в различные приемники. Затем TransformerHandler прослушивает SAX ContentHandler, анализирует события и преобразует их в результат.

Методы startElement() и endElement()10 из TransformerHandler класс создали теги в XML-файле. Парсер вызывал метод startElement() в начале каждого элемента и endElement() в конце каждого элемента XML-документа.

import com.lowagie.text.*; 
import com.lowagie.text.pdf.*; 
import java.io.*; 
import javax.xml.parsers.*; 
import javax.xml.transform.*; 
import javax.xml.transform.sax.*; 
import javax.xml.transform.stream.*; 
import org.xml.sax.*; 
import org.xml.sax.helpers.*; 

public class Cp2x { 

     static StreamResult streamResult; 
     static TransformerHandler handler; 
     static AttributesImpl atts; 

     public static void main(String[] args) throws IOException { 

       try { 
         Document document = new Document(); 
         document.open(); 
         PdfReader reader = new PdfReader("C:\\helloworld.pdf"); 
         PdfDictionary page = reader.getPageN(1); 
         PRIndirectReference objectReference = (PRIndirectReference) page 
             .get(PdfName.CONTENTS); 
         PRStream stream = (PRStream) PdfReader 
             .getPdfObject(objectReference); 
         byte[] streamBytes = PdfReader.getStreamBytes(stream); 
         PRTokeniser tokeniser = new PRTokeniser(streamBytes); 

         StringBuffer string_buffer = new StringBuffer(); 
         while (tokeniser.nextToken()) { 
           if (tokeniser.getTokenType() == PRTokeniser.TK_STRING) { 
             string_buffer.append(tokeniser.getStringValue()); 
           } 
         } 
         String test = string_buffer.toString(); 
         streamResult = new StreamResult("test.xml"); 
         initXML(); 
         process(test); 
         closeXML(); 
         document.add(new Paragraph("..")); 
         document.close(); 
       } catch (Exception e) { 
       } 
     } 

     public static void initXML() throws ParserConfigurationException, 
         TransformerConfigurationException, SAXException { 
       SAXTransformerFactory tf = (SAXTransformerFactory) SAXTransformerFactory 
           .newInstance(); 

       handler = tf.newTransformerHandler(); 
       Transformer serializer = handler.getTransformer(); 
       serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 
       serializer.setOutputProperty(
           "{http://xml.apache.org/xslt}indent-amount", "4"); 
       serializer.setOutputProperty(OutputKeys.INDENT, "yes"); 
       handler.setResult(streamResult); 
       handler.startDocument(); 
       atts = new AttributesImpl(); 
       handler.startElement("", "", "Document", atts); 
     } 

     public static void process(String s) throws SAXException { 
       String[] elements = s.split("\\|"); 
       atts.clear(); 
       handler.startElement("", "", "Note", atts); 
       handler.characters(elements[0].toCharArray(), 0, elements[0].length()); 
       handler.endElement("", "", "Note"); 
     } 

     public static void closeXML() throws SAXException { 
       handler.endElement("", "", "Document"); 
       handler.endDocument(); 
     } 
} 
+0

«Результат немного странный, все символы становятся символами», похоже, проблема с кодировкой. чтобы преобразовать байтовый массив в String. может использовать StringBuilder вместо StingBuffer в зависимости от варианта использования. – sudmong

+0

Вы также игнорируете все содержимое, которое присутствует в XObjects; как вы собираетесь их захватить в XML? Также: вы только читаете объекты String, и вы не учитываете фактический порядок текста. Почему вы используете устаревшую версию iText? Текущая версия iText имеет гораздо лучший парсер. Он может даже преобразовать Tagged PDF в XML-файл, используя TaggedPdfReaderTool: http://itextpdf.com/examples/iia.php?id=281 (который, очевидно, будет генерировать XML только в том случае, если ваш PDF был помечен). –

ответ

1

Как @sudmong говорит, есть проблема кодирования: PRTokeniser не должен использоваться для чтения строк из внутри страниц потоков контента, он работает должным образом только за их пределами, поскольку он предполагает специальную кодировку в то время как кодирование строк внутри потоков содержимого страницы полностью зависит от кодировки текущего шрифта на этом этапе описания содержимого. Ср ISO 32000-1 разделы 7.3.4.2 Литеральные строки для потоков внешних потоков контента и 9.6.6 Кодировка символов для строк внутри потоков контента.

Как указывает @BrunoLowagie, вы тем самым полностью игнорируете, что содержание страницы не только внутри непосредственного потока содержимого страницы, но и в объектах XObjects, на которые ссылается оттуда, ср. ISO 32000-1 раздел 8.10 Форма XObjects. Он также указывает, что строки в потоке содержимого не обязательно должны быть в порядке чтения, ср. ibidem раздел 9.4 Текст Объекты.

Вы также игнорировать, что значение параметра Содержание словаря страницы может быть либо поток или массив потоков:

Значение должно быть либо один поток или массив потоков. Если значение представляет собой массив, эффект должен быть таким, как если бы все потоки в массиве были объединены, чтобы сформировать один поток. Соответствующие авторы могут создавать объекты изображения и другие ресурсы по мере их возникновения, даже если они прерывают поток контента. Разделение потоков может происходить только на границах между лексическими жетонами (см. 7.2 «Лексические соглашения»), но не должно быть связано с логическим контентом или организацией страницы. Приложения, которые потребляют или создают PDF-файлы, не должны сохранять существующую структуру массива Contents. Соответствующие авторы не должны создавать массив содержимого, не содержащий элементов.

раздел 7.7.3.3 Page Объекты в ISO 32000-1

Если вы действительно хотите программировать синтаксический анализатор самостоятельно, вам лучше изучить ISO 32000-1 первый.

В противном случае посмотрите на пакет iText, который уже является отличным инструментом для анализа содержимого PDF. Если вам это нравится, вы можете улучшить его.

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