IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Format d'échange (XML, JSON...) Java Discussion :

Extraire métadonnées (intégrées dans un XML) d'un fichier PDF [JDOM]


Sujet :

Format d'échange (XML, JSON...) Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Par défaut Extraire métadonnées (intégrées dans un XML) d'un fichier PDF
    Bonjour à tous,

    je me permets de vous demander de l'aide car cela fait depuis plusieurs jours que je cherche une solution, mais sans y arriver.
    Donc voilà, je bosse en ce moment sur un projet qui consiste à extraire les métadonnées de PDF pour les intégrer dans une base de données.

    Les métadonnées sont présents en XML qui ait lui même intégrer dans les fichiers PDF.

    Le problème étant qu'Adobe n'a pas fait les choses simples et les XML contenues dans les PDF sont une vraie plaie.

    Enfin voici un exemple d'XML que j'ai extrais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    <?xpacket begin="?" id="W5M0MpCehiHzreSzNTczkc9d"?>
    <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.2-c001 63.139439, 2010/09/27-13:37:26        ">
       <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
          <rdf:Description rdf:about=""
                xmlns:xmp="http://ns.adobe.com/xap/1.0/">
             <xmp:CreateDate>2011-12-19T16:38:21+01:00</xmp:CreateDate>
             <xmp:ModifyDate>2011-12-19T16:44:21+01:00</xmp:ModifyDate>
             <xmp:MetadataDate>2011-12-19T16:44:21+01:00</xmp:MetadataDate>
          </rdf:Description>
          <rdf:Description rdf:about=""
                xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
             <pdf:Producer>doPDF Ver 7.2 Build 370 (Windows XP Professional Edition  (SP 3) - Version: 5.1.2600 (x86))</pdf:Producer>
          </rdf:Description>
          <rdf:Description rdf:about=""
                xmlns:dc="http://purl.org/dc/elements/1.1/">
             <dc:identifier>RAPPORT0001</dc:identifier>
             <dc:source>56</dc:source>
             <dc:coverage>Trédion</dc:coverage>
             <dc:format>application/pdf</dc:format>
             <dc:title>
                <rdf:Alt>
                   <rdf:li xml:lang="x-default">Ceci est le nom de mon rapport</rdf:li>
                </rdf:Alt>
             </dc:title>
             <dc:publisher>
                <rdf:Bag>
                   <rdf:li>Nom de l'entreprise</rdf:li>
                </rdf:Bag>
             </dc:publisher>
             <dc:date>
                <rdf:Seq>
                   <rdf:li>2011</rdf:li>
                </rdf:Seq>
             </dc:date>
             <dc:creator>
                <rdf:Seq>
                   <rdf:li>Dupont Luc</rdf:li>
                </rdf:Seq>
             </dc:creator>
             <dc:rights>
                <rdf:Alt>
                   <rdf:li xml:lang="x-default">Publiable</rdf:li>
                </rdf:Alt>
             </dc:rights>
             <dc:description>
                <rdf:Alt>
                   <rdf:li xml:lang="x-default">Type d'opération</rdf:li>
                </rdf:Alt>
             </dc:description>
          </rdf:Description>
          <rdf:Description rdf:about=""
                xmlns:dex="http://ns.optimasc.com/dex/1.0/">
             <dex:licensetype>unknown</dex:licensetype>
             <dex:ffid>000000001-60-0015930</dex:ffid>
          </rdf:Description>
          <rdf:Description rdf:about=""
                xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/">
             <illustrator:StartupProfile>Print</illustrator:StartupProfile>
          </rdf:Description>
          <rdf:Description rdf:about=""
                xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
             <xmpMM:DocumentID>uuid:ba35b60b-e3bb-494d-94e9-436b5a60ce6b</xmpMM:DocumentID>
             <xmpMM:InstanceID>uuid:9ac3b895-bd69-4145-ad3b-b510126ad3af</xmpMM:InstanceID>
          </rdf:Description>
       </rdf:RDF>
    </x:xmpmeta>            
    <?xpacket end="w"?>
    Donc je voudrais récupérer les données contenues dans les balises suivantes:
    - "RAPPORT0001" qui se trouve dans la balise = dc:identifier

    - "56" qui se trouve dans = dc:source

    - "Trédion" qui se trouve dans = dc:coverage

    - "Ceci est le nom de mon rapport" qui se trouve dans = dc:title et dans le sous-élément rdf:Alt

    - "2011" qui se trouve dans = dc:date et dans le sous-élément rdf:Seq et rdf:li

    - "Dupont Luc" = dc:creator et dans le sous-élément rdf:Seq et rdf:li

    - "Publiable" = dc:rights et dans le sous-élément rdf:Alt et rdf;li

    - et enfin "Type d'opération" qui se trouve dans dc:description et rdf:Alt

  2. #2
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Par défaut suite
    Bon, j'avais déjà commencé à écrire un code avec DOM :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    public static void lectureMetadataXML(String metadonneesXML) throws ParserConfigurationException, SAXException, IOException {
     
            DocumentBuilderFactory usineParseurXml;
            DocumentBuilder parseurXml;
     
            Document documentXML;
            Element racine;
            NodeList listeXml;
            Node enfantXml;
     
    //-----------------Création de l'usine à parseurXml--------------------------
            usineParseurXml = DocumentBuilderFactory.newInstance();
            usineParseurXml.setIgnoringComments(true);
            usineParseurXml.setIgnoringElementContentWhitespace(true);
            // vérification de la présence d'un fichier DTD
          //  usineParseurXml.setValidating(true);
     
    //-----Création du parseur et association au gestionnaire d'erreur-----------
            parseurXml = usineParseurXml.newDocumentBuilder();
            parseurXml.setErrorHandler(new ErreurDtd());
     
    //--------------Conversion des données reçues en Document--------------------
            documentXML = parseurXml.parse(new InputSource(new StringReader(metadonneesXML)));
     
    //----Récupération de l'élément racine de l'arbre et affichage de son nom----
            racine = documentXML.getDocumentElement();
            System.out.println("Nom de la racine : " + racine.getNodeName());
     
    //----------------Récupération des enfants de la racine----------------------
          listeXml = racine.getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", "dc:identifier");
     
          listeXml = racine.getChildNodes();
     
          for (int i = 0; i < listeXml.getLength(); i++)
          {
             enfantXml = listeXml.item(i);
     
             System.out.println("Nom :   " + enfantXml.getNodeName());
     
             for(int j=0; j <enfantXml.getChildNodes().getLength(); j++)
             {
                String nomEnfant;
                nomEnfant = enfantXml.getChildNodes().item(j).getTextContent();
                System.out.println("ChildNodes : " +nomEnfant);
             }
       }
     
    }
    Je voulais faire un if sur le nom de la balise afin récupérer les données. exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if(balise.equals()=="dc:identifier")
    {
    //traitement
    }
    Mais je n'arrive pas à récupérer le nom de la balise.

    Donc, au final, j'ai tout repris à zéro et je suis partis sur du JDOM, mais je suis autant perdu.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ce sera effectivement bien plus simple avec JDOM.
    Mais vu que les données sont perdues assez profond dans la hiérarchie de balises, et qu'il y a des namespaces, ça reste assez compliqué.

    Voici un exemple qui va chercher ta balise <dc:identifier> sans se soucier de là où elle se trouve :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static void lectureMetadataXML(String metadonneesXML) throws JDOMException, IOException {
      SAXBuilder saxBuilder = new SAXBuilder();
      Document document = saxBuilder.build(new StringReader(metadonneesXML));
     
      // tiré de xmlns:dc
      Namespace namespaceDc = Namespace.getNamespace("dc", "http://purl.org/dc/elements/1.1/");
     
      Element identifierElt = document.getDescendants(Filters.element("identifier", namespaceDc)).next();
      String identifier = identifierElt.getText();
      System.out.println(identifier);
    }
    Toute l'astuce est de chercher n'importe quelle balise 'identifier' dans le namespace 'dc' et compter sur le fait qu'il n'y en a qu'une, autrement dit, que la première est la bonne.

    C'est ça l'idée de getDescendants(), auquel on demande de filtrer ce qu'il trouve, et de ne garder que les balises 'identifier' dans le namespace 'dc'.
    On appelle next() pour prendre le premier résultat, et puis on s'arrête là.

    Cela nous a donné un Element, la balise <dc:identifier>. Ce qui nous intéresse c'est son contenu texte, donc getText(). Voilà, problème résolu en trois lignes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Par défaut
    merci beaucoup @thelvin, j'essaye ça

  5. #5
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2012
    Messages : 11
    Par défaut
    Ca marche merci pour ton aide et tes explications claires.

    Par contre, j'ai un autre problème.
    Je veux maintenant pouvoir lire les métadonnées qui sont encore plus profonds dans la hiérarchie comme par exemple : "Ceci est le nom de mon rapport" qui se te trouve dans la balise rdf:li, elle-même contenu dans rdf:Alt et elle-même contenu dans dc:title.

    Il y a t'il un moyen plus simple que ceci?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
          Element titleElt = document.getDescendants(Filters.element("title", namespaceDc)).next();
          List listeTitleElt = titleElt.getChildren();
          Iterator iterator1 = listeTitleElt.iterator();
          while(iterator1.hasNext())
          {
              Element courant = (Element)iterator1.next();
     
              //On affiche le nom de l'element courant        
              List listEnfant = courant.getChildren();
              Iterator iterator2 = listEnfant.iterator();
              while(iterator2.hasNext())
              {
                  Element courant2 = (Element)iterator2.next();
                  String courant2XML = courant2.getText();
                  System.out.println(courant2XML);
              }       
         }
    EDIT : Enfin pas grave, je laisse la boucle sur les Iterators pour les données présentes encore plus profondément dans la hiérarchie, le principal est que ça marche.
    Encore merci à thelvin, sans lui je serais en train de galérer. Je mets le sujet en résolu.

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Tu pouvais quand même faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Element containerElt = titleElt.getChildren().get(0);
    String title = containerElt.getChildren().get(0).getText();
    En gros, getChildren().get(0) permet de prendre le premier élément fils. Pratique.

    En réalité, il faudrait peut-être gérer mieux que ça, parce que les élément <rdf:Alt> et <rdf:li> ne sont pas censés être obligatoires, et il faut savoir quoi faire quand ils ne sont pas là. Dans le même genre, le principe de <rdf:li> c'est qu'il devrait y en avoir plusieurs, est-ce qu'on est vraiment censé ne prendre que le premier quand il y en a vraiment plusieurs ? Bref, des questions d'intégration.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Variables dans le nom d'un fichier PDF
    Par sardaucar dans le forum VBA Access
    Réponses: 2
    Dernier message: 11/05/2014, 13h08
  2. [XSLT 2.0] Lire une image base64 intégrée dans un XML
    Par alouani dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 10/05/2011, 10h18
  3. Ecrire dans une zone de texte fichier PDF
    Par senseo dans le forum Général VBA
    Réponses: 0
    Dernier message: 17/03/2010, 07h42
  4. [PDF] PHP et recherche dans le contenu d'un fichier PDF
    Par bass17 dans le forum Bibliothèques et frameworks
    Réponses: 8
    Dernier message: 16/02/2007, 11h54
  5. [XML][PHP]Extraire balise img dans une balise xml
    Par thierry232323 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 17/10/2006, 13h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo