Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Extraire les tableaux des PDF via les API d’accessibilité

BlueHats
December 06, 2018

Extraire les tableaux des PDF via les API d’accessibilité

BlueHats

December 06, 2018
Tweet

More Decks by BlueHats

Other Decks in Technology

Transcript

  1. Extraire les tableaux des PDF via les API d’accessibilité Orateur

    : Erwan le Gall expert AccessiWeb en évaluation Direction du numérique pour l’Éducation
  2. Exemple utilisé le RAP* de la mission « enseignement scolaire

    » du programme 214 soutien de la politique de l’Éducation nationale (annexe au projet de loi de règlement des comptes et rapport de gestion) * rapport annuel de performance
  3. Résultat n° 1 INDICATEUR 1.1 Nombre de postes d'enseignants non⮠

    ⮣pourvus à la rentrée scolaire et⮠ ⮣durée moyenne des vacances de postes (enseignement public) (du point de vue de l'usager) Unité 2015 Réalisation 2016 Réalisation 2017 Prévision PAP 2017 2017 Prévision actualisée PAP 2018 2017 Réalisation Postes enseignants du⮠ ⮣premier degré nombre 1 204⮠ ⮣1 008 Postes enseignants du second degré nombre⮠ ⮣ 2 597 2 531 Durée moyenne⮠ ⮣ de vacance de poste second degré jour 18,14 22,48 < 12 2017 Cible PAP 2017 < 750 < 750 1 074 < 500 < 1 800 < 1 800 3 049 < 1 200 < 12 24,3 < 12
  4. Résultat n° 1 INDICATEUR 1.1 Nombre de postes d'enseignants non⮠

    ⮣pourvus à la rentrée scolaire et⮠ ⮣durée moyenne des vacances de postes (enseignement public) (du point de vue de l'usager) Unité 2015 Réalisation 2016 Réalisation 2017 Prévision PAP 2017 2017 Prévision actualisée PAP 2018 2017 Réalisation Postes enseignants du⮠ ⮣premier degré nombre 1 204⮠ ⮣1 008 Postes enseignants du second degré nombre⮠ ⮣ 2 597 2 531 Durée moyenne⮠ ⮣ de vacance de poste second degré jour 18,14 22,48 < 12 2017 Cible PAP 2017 < 750 < 750 1 074 < 500 < 1 800 < 1 800 3 049 < 1 200 < 12 24,3 < 12 ① ② ① ②
  5. Résultat n° 2a INDICATEUR 1.1 Nombre de postes d'enseignants non

    pourvus à la rentrée scolaire et durée moyenne des vacances de postes (enseignement public) (du point de vue de l'usager) Unité 2015 Réalisation 2016 Réalisation 2017 Prévision PAP 2017 2017 Prévision actualisée PAP 2018 2017 Réalisation 2017 Cible PAP 2017 Postes enseignants du premier degré nombre 1 204 1 008 < 750 < 750 1 074 < 500 Postes enseignants du second degré nombre 2 597 2 531 < 1 800 < 1 800 3 049 < 1 200 Durée moyenne de vacance de poste second degré jour 18,14 22,48 < 12 < 12 24,3 < 12
  6. Résultat n° 2b INDICATEUR 1.1 Nombre de postes d'enseignants non

    pourvus à la rentrée scolaire et durée moyenne des vacances de postes (enseignement public) (du point de vue de l'usager) Unité 2015 Réalisation 2016 Réalisation 2017 Prévision PAP 2017 2017 Prévision actualisée PAP 2018 2017 Réalisation Postes enseignants du premier degré nombre 1 204 1 008 Postes enseignants du second degré nombre 2 597 2 531 Durée moyenne de vacance de poste second degré jour 18,14 22,48 < 12 2017 Cible PAP 2017 < 750 < 750 1 074 < 500 < 1 800 < 1 800 3 049 < 1 200 < 12 24,3 < 12
  7. Principe Bus logiciel équivalent au bus graphique GDI (pour imprimante

    et écran) utilisant une structure de données textuelle (arbre d’accessibilité)
  8. Résultat initial n°3 Table (block): /Placement /Block /SpaceBefore 16 /Width

    997.8 /Height 185.7 /BBox [39.7 437.4 538.6 530.3] TR: /Placement /Block TH: /Placement /Inline /Width 283.7 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center TH: /Placement /Inline /Width 102 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center "Unité" TH: /Placement /Inline /Width 102 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center "2015 " " Réalisation " […] TD: /Placement /Inline /Width 102 /Height 41.2 P (block): /Placement /Block /SpaceBefore 4 /SpaceAfter 4 /TextAlign /Center "24,3 " TD: /Placement /Inline /Width 102.1 /Height 41.2 P (block): /Placement /Block /SpaceBefore 4 /SpaceAfter 4 /TextAlign /Center "< 12 "
  9. Résultat initial n°3 Table (block): /Placement /Block /SpaceBefore 16 /Width

    997.8 /Height 185.7 /BBox [39.7 437.4 538.6 530.3] TR: /Placement /Block TH: /Placement /Inline /Width 283.7 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center TH: /Placement /Inline /Width 102 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center "Unité" TH: /Placement /Inline /Width 102 /Height 78.3 P (block): /Placement /Block /SpaceBefore 6 /SpaceAfter 24 /TextAlign /Center "2015 " " Réalisation " […] TD: /Placement /Inline /Width 102 /Height 41.2 P (block): /Placement /Block /SpaceBefore 4 /SpaceAfter 4 /TextAlign /Center "24,3 " TD: /Placement /Inline /Width 102.1 /Height 41.2 P (block): /Placement /Block /SpaceBefore 4 /SpaceAfter 4 /TextAlign /Center "< 12 "
  10. Résultat initial n°3 Table (block): TR: TH: TH: Unité" TH:

    "2015 " " Réalisation " TH: "2016 " " Réalisation " TH: "2017 " "Prévision" "PAP 2017" TH: "2017 " "Prévision " "actualisée""PAP 2018" TH: "2017 " "Réalisation" TH: "2017 " "Cible" "PAP 2017" TR: TD: " Postes enseignants⮠ ⮣du premier degré " TD: "nombre " TD: "1 204 " TD: "1 008 " TD: "< 750 " TD: "< 750 " TD: "1 074 " TD: "< 500 " TR: TD: "Postes enseignants⮠ ⮣du second degré " TD: "nombre " TD: "2 597 " TD: "2 531 " TD: "< 1 800 " TD: "< 1 800 " TD: "3 049 " TD: "< 1 200 " […]
  11. TR: TD: " Postes enseignants⮠ ⮣du premier degré " TD:

    "nombre " TD: "1 204 " TD: "1 008 " TD: "< 750 " TD: "< 750 " TD: "1 074 " TD: "< 500 " TR: TD: "Postes enseignants⮠ ⮣du second degré " TD: "nombre " TD: "2 597 " TD: "2 531 " TD: "< 1 800 " TD: "< 1 800 " TD: "3 049 " TD: "< 1 200 " […] Résultat initial n°3 Table (block): TR: TH: TH: Unité" TH: "2015 " " Réalisation " TH: "2016 " " Réalisation " TH: "2017 " "Prévision" "PAP 2017" TH: "2017 " "Prévision " "actualisée""PAP 2018" TH: "2017 " "Réalisation" TH: "2017 " "Cible" "PAP 2017"
  12. TR: TD: " Postes enseignants⮠ ⮣du premier degré " TD:

    "nombre " TD: "1 204 " TD: "1 008 " TD: "< 750 " TD: "< 750 " TD: "1 074 " TD: "< 500 " TR: TD: "Postes enseignants⮠ ⮣du second degré " TD: "nombre " TD: "2 597 " TD: "2 531 " TD: "< 1 800 " TD: "< 1 800 " TD: "3 049 " TD: "< 1 200 " […] Résultat initial n°3 Table (block): TR: TH: TH: Unité" TH: "2015 " " Réalisation " TH: "2016 " " Réalisation " TH: "2017 " "Prévision" "PAP 2017" TH: "2017 " "Prévision " "actualisée""PAP 2018" TH: "2017 " "Réalisation" TH: "2017 " "Cible" "PAP 2017"
  13. Code source de pdfinfo adapté static void printStruct(const StructElement *element,

    unsigned indent) { if (printStructureText && element->isContent()) { GooString *text = element->getText(gFalse); if (text) { printf("%s\n", text->getCString()); } else { printf("(No content?)\n"); } delete text; } if (!element->isContent()) { printIndent(indent); printf("<%s>", element->getTypeName()); putchar('\n'); for (unsigned i = 0; i < element->getNumChildren(); i++) { PrintStruct( element→getChild(i), indent + 1); } printIndent(indent); printf("</%s>", element->getTypeName()); putchar('\n'); } }
  14. Code source de pdfinfo adapté static void printStruct(const StructElement *element,

    unsigned indent) { if (printStructureText && element->isContent()) { GooString *text = element->getText(gFalse); if (text) { printf("%s\n", text->getCString()); } else { printf("(No content?)\n"); } delete text; } if (!element->isContent()) { printIndent(indent); printf("<%s>", element->getTypeName()); putchar('\n'); for (unsigned i = 0; i < element->getNumChildren(); i++) { PrintStruct( element→getChild(i), indent + 1); } printIndent(indent); printf("</%s>", element->getTypeName()); putchar('\n'); } } TEXTE BALISE
  15. Code source de pdfinfo adapté static void printStruct(const StructElement *element,

    unsigned indent) { if (printStructureText && element->isContent()) { GooString *text = element->getText(gFalse); if (text) { printf("%s\n", text->getCString()); } else { printf("(No content?)\n"); } delete text; } if (!element->isContent()) { printIndent(indent); printf("<%s>", element->getTypeName()); putchar('\n'); for (unsigned i = 0; i < element->getNumChildren(); i++) { PrintStruct( element→getChild(i), indent + 1); } printIndent(indent); printf("</%s>", element->getTypeName()); putchar('\n'); } }
  16. Résultat intermédiaire n°3 <Table> <TR> <TH> <P> </P> </TH> <TH>

    <P> Unité </P> </TH> <TH> <P> 2015 Réalisation </P> </TH> <TH> <P> 2016 Réalisation </P> </TH> <TH> <P> 2017 Prévision PAP 2017 </P> </TH> <TH> <P> 2017 Prévision actualisée PAP 2018 </P> </TH> <TH> <P> 2017 Réalisation </P> </TH> <TR> <TD> <P> Postes enseignants du premier degré </P> </TD> <TD> <P> nombre </P> </TD> <TD> <P> 1 204 </P> </TD> <TD> <P> 1 008 </P> </TD> <TD> <P> < 750 </P> </TD> <TD> <P> < 750 </P> </TD> <TD> <P> 1 074 </P> </TD> <TD> <P> < 500 </P> </TD> </TR> <TR> […] </Table>
  17. Code source de pdfinfo adapté v2 static std::string myStringReplace(const std::string

    &inString, const std::string &oldToken, const std::string &newToken) { std::string result = inString; size_t foundLoc; int advance = 0; do { foundLoc = result.find(oldToken, advance); if (foundLoc != std::string::npos){ result.replace(foundLoc, oldToken.length(), newToken); advance = foundLoc + newToken.length(); } } while (foundLoc != std::string::npos ); return result; } static std::string myXmlTokenReplace(const char *inString){ std::string myString(inString); myString = myStringReplace( myStringReplace( myStringReplace( myStringReplace( myStringReplace(myString, "&", "&amp;" ), "<", "&lt;" ), "\"", "&quot;" ), "'", "&apos;" ), ">", "&gt;" ) ; return myString; }
  18. Code source de pdfinfo adapté v2 static void printStruct(const StructElement

    *element, unsigned indent) { if (printStructureText && element->isContent()) { GooString *text = element->getText(gFalse); // printIndent(indent); if (text) { std::string myString = myXmlTokenReplace(text->getCString()); printf("%s\n", myString.c_str()); //~ printf("%s\n", text->getCString()); } else { printf("(No content?)\n"); } delete text; } if (!element->isContent()) { printIndent(indent); printf("<%s>", element->getTypeName()); putchar('\n'); for (unsigned i = 0; i < element->getNumChildren(); i++) { printStruct(element->getChild(i), indent + 1); } printIndent(indent); printf("</%s>", element->getTypeName()); putchar('\n'); } }
  19. Résultat intermédiaire n°3 <Table> <TR> <TH> <P> </P> </TH> <TH>

    <P> Unité </P> </TH> <TH> <P> 2015 Réalisation </P> </TH> <TH> <P> 2016 Réalisation </P> </TH> <TH> <P> 2017 Prévision PAP 2017 </P> </TH> <TH> <P> 2017 Prévision actualisée PAP 2018 </P> </TH> <TH> <P> 2017 Réalisation </P> </TH> <TR> <TD> <P> Postes enseignants du premier degré </P> </TD> <TD> <P> nombre </P> </TD> <TD> <P> 1 204 </P> </TD> <TD> <P> 1 008 </P> </TD> <TD> <P> &apos ; 750 </P> </ TD> <TD> <P> &apos ; 750 </P> </TD> <TD> <P> 1 074 </P> </TD> <TD> <P> &apos ; 500 </P> </TD> </TR> <TR> […] </Table>
  20. Résultat final n°3 Remplacer la balise racine <Document> par un

    entête de page HTML <html><head></head><body> et et la balise fermante </Document> par un pied HTML </body></html>
  21. Conclusion 2/2 Il est possible de simuler un utilisateur handicapé

    via les API d’accessibilité pour les tests fonctionnels