2013-02-12 4 views
0

J'essaie de créer un prototype pour convertir un fichier PDF en fichier XML. Le résultat est un peu étrange, tous les personnages deviennent des symboles. Je pense que le bug est où le StringBuffer prend les données du tableau d'octets. Quelqu'un avec des connaissances Java peut-il aider s'il vous plaît?Utilisation de Java pour convertir le PDF en XML

Ce logiciel prototype utilise l'API iText. Pour lire le fichier PDF, nous avons utilisé la classe PDFReader. Les données sont d'abord converties en un tableau d'octets, puis avec l'utilisation de Stringbuffer, elles seront à nouveau converties en chaîne. Ensuite, nous avons utilisé StreamResult qui sert de support pour le résultat transformé en XML. Par la suite, la classe Transformer traite le code XML à partir de diverses sources et écrit la sortie de la transformation dans divers récepteurs. Ensuite, TransformerHandler écoute SAX ContentHandler, analyse les événements et les transforme en résultat. Les méthodes startElement() et endElement() de TransformerHandler ont créé les balises dans le fichier xml. L'analyseur a appelé la méthode startElement() au début de chaque élément et endElement() à la fin de chaque élément du document 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

« Le résultat est un peu étrange, tous les personnages deviennent des symboles » semble comme l'encodage question. passez l'encodage lors de la conversion d'un tableau d'octets en String. peut utiliser StringBuilder au lieu de StingBuffer selon le cas d'utilisation. – sudmong

+0

Vous ignorez également tout le contenu présent dans XObjects; comment allez-vous les capturer en XML? Aussi: vous ne lisez que des objets String, et vous ne tenez pas compte de l'ordre réel du texte. Pourquoi utilisez-vous une version obsolète d'iText? La version actuelle de iText a un bien meilleur analyseur. Il peut même convertir un PDF balisé en un fichier XML à l'aide de TaggedPdfReaderTool: http://itextpdf.com/examples/iia.php?id=281 (ce qui, évidemment, ne produira du XML que si votre PDF a été balisé). –

Répondre

1

Comme dit @sudmong, il y a un problème d'encodage: Le PRTokeniser ne doit pas être utilisé pour lire des chaînes de à l'intérieur page flux de contenu, il ne fonctionne correctement que en dehors d'eux, car elle suppose un codage de caractères spéciaux tandis que le le codage des chaînes à l'intérieur des flux de contenu de la page dépend entièrement du codage de la police en cours à cette étape de la description du contenu. Cf. ISO 32000-1 sections 7.3.4.2 Chaînes littérales pour les chaînes en dehors des flux de contenu et 9.6.6 Encodage des caractères pour les chaînes dans les flux de contenu. Comme le souligne @BrunoLowagie, vous ignorez complètement que le contenu de la page ne se trouve pas seulement dans le flux de contenu de la page immédiate, mais aussi dans les XObjets référencés à partir de là, cf. ISO 32000-1 section 8.10 Forme XObjects. Il souligne également que les chaînes dans le flux de contenu n'ont pas besoin d'être dans l'ordre de lecture, cf. ibidem section 9.4 Objets texte.

Vous ignorez également que la valeur de l'entrée Contenu du dictionnaire de la page peut être un flux ou un tableau de flux:

La valeur doit être un seul flux ou un tableau de flux. Si la valeur est un tableau, l'effet sera comme si tous les flux du tableau étaient concaténés, dans l'ordre, pour former un seul flux. Les rédacteurs conformes peuvent créer des objets image et d'autres ressources lorsqu'elles se produisent, même si elles interrompent le flux de contenu. La division entre les flux ne peut se produire qu'aux limites entre les jetons lexicaux (voir 7.2, «Conventions lexicales») mais ne doit pas être liée au contenu ou à l'organisation logique de la page. Les applications qui consomment ou produisent des fichiers PDF n'ont pas besoin de conserver la structure existante du tableau Contents. Les rédacteurs conformes ne doivent pas créer de tableau de contenu ne contenant aucun élément.

section 7.7.3.3 page Objets dans ISO 32000-1

Si vous voulez vraiment vraiment programmer un analyseur vous, vous feriez mieux d'étudier ISO 32000-1 premier.

regarder Sinon le paquet ...text.pdf.parser de iText qui est déjà tout à fait un bon outil pour analyser le contenu PDF. Si vous en ressentez le besoin, vous pouvez l'améliorer.