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

Langage PHP Discussion :

getElementsByTagNameNS : Récupérer les balises w:Sdt d'un fichier Word au format html


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur commercial
    Inscrit en
    Avril 2017
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur commercial

    Informations forums :
    Inscription : Avril 2017
    Messages : 46
    Par défaut getElementsByTagNameNS : Récupérer les balises w:Sdt d'un fichier Word au format html
    Bonjour à tous,

    Je débute le PHP depuis quelques jours et dans le cadre de mon projet, je dois lire un fichier word enregistré au format html (TemplateDemo.html) puis récupérer le contenu des balises de "w:Sdt" présente dans ce fichier.

    Extrait du fichier TemplateDemo.html:

    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
    <html xmlns:v="urn:schemas-microsoft-com:vml"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:w="urn:schemas-microsoft-com:office:word"
    xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
    xmlns="http://www.w3.org/TR/REC-html40">
     
    </head>
     
    <body lang=FR style='tab-interval:35.4pt'>
     
    <div class=WordSection1>
     
    <p class=MsoNormal>Bonjour <w:Sdt DocPart="06F41A9E3F1AD443B6220BEA9C32380D"
     Title="NOM" SdtTag="VAR" ID="950663817">NOM1</w:Sdt>,</p>
     
    <p class=MsoNormal><o:p>&nbsp;</o:p></p>
    Voici mon code PhP pour lire le contenue du fichier TemplateDemo.html et récupérer le contenu des balises <w:Sdt>:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Extract data from TemplateDemo.html
    $content = file_get_contents( dirname( __FILE__ ) . '/TemplateDemo.html' );
      if ($content === false) echo "ERROR CANNOT READ TEMPLATEDEMO file";
    //Extraction of <w:Std> tags included in Word Template
    $dom = new DOMDocument();
    $dom->loadHTML($content);
    		foreach ($dom->getElementsByTagNameNS('*', 'w:std') as $element) {
        echo 'local name: ', $element->localName, ', prefix: ', $element->prefix, "\n";
    }
    Le echo ne me renvoi rien. J'ai essayé de suivre à la lettre la documentation PhP:

    https://www.php.net/manual/fr/domdoc...ytagnamens.php

    Est ce que quelqu'un peut m'aiguiller svp ?

    AG

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach ($dom->getElementsByTagNameNS('*', 'w:std') as $element) {
    Le deuxième paramètre de getElementsByTagNameNS() doit être le nom local de l'élément donc il faut enlever le préfixe. En plus ta balise de s'appelle pas std mais Sdt et il faut respecter la casse.

    Dernière chose tu devrais plutôt tenter ta chance avec loadXML plutôt qu'avec loadHTML.

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur commercial
    Inscrit en
    Avril 2017
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur commercial

    Informations forums :
    Inscription : Avril 2017
    Messages : 46
    Par défaut
    Bonjour CosmoKnacki,

    Merci beaucoup de me donner des pistes. Je débute et j'ai l'impression de pas m'attaquer à du super facile...

    J'ai modifié le code comme ci dessous mais le Echo affiche toujours rien. Peux être à cause du NameSpace qui est sur "*"? J'ai essayer de mettre 'urn:schemas-microsoft-com:office:word' mais ça ne change rien non plus.

    Je comprends à ta dernière phrase que ce serait peut être plus simple si j'enregistre le document Word en .xml et que je fasse loadXML. Je vais essayer demain et je vous informe du résultat.

    Encore merci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Extract data from TemplateDemo.html
    $content = file_get_contents( dirname( __FILE__ ) . '/TemplateDemo.html' );
      if ($content === false) echo "ERROR CANNOT READ TEMPLATEDEMO file";
    //Extraction of <w:Std> tags included in Word Template
    $dom = new DOMDocument();
    $dom->loadHTML($content);
    		foreach ($dom->getElementsByTagNameNS('*', 'Std') as $element) {
        echo 'local name: ', $element->localName, ', prefix: ', $element->prefix, "\n";
    }

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    En fait, avec le peu que tu as montré de ton document, le problème est double:
    • Si tu charges ton document avec DOMDocument::loadHTML, celui-ci va sucrer tous les préfixes d'espaces de noms inconnues des éléments (car en html DOMDocument applique des corrections automatiques).
    • Si tu charges ton document avec DOMDocument::loadXML, le parser va tiquer à la moindre incartade (comme une balise non-fermée, un attribut dont la valeur n'est pas entre quotes simples ou doubles, une entité inconnue comme &nbsp;) et tu ne pourras pas exploiter le document car l'arbre DOM ne sera même pas construit (ce coup ci, pas de corrections automatique, un document est du XML ou il ne l'est pas).


    Pour prendre la mesure de tout ça, tu peux faire ce test qui va t'afficher les erreurs rencontrées:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    libxml_use_internal_errors(true);
    $dom = new DOMDocument;
    $dom->loadXML($content); 
    print_r(libxml_get_errors());
    Puis remplace loadXML par loadHTML et tu verras que les erreurs relevées ne sont pas toutes les mêmes.

    Bref, pour t'en tirer facilement, ce que tu peux faire c'est de charger ton document en html, mais tu devras dire adieu aux préfixes d'espaces de noms pour l'exploiter, donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    libxml_use_internal_errors(true);
    $dom = new DOMDocument;
    $dom->loadHTML($content); 
     
    foreach ($dom->getElementsByTagName('sdt') as $element) { 
        //...
    }
    L'autre solution serait de "réparer" le document pour en faire du XML (en exploitant les informations données par libxml_get_errors()), mais c'est fastidieux et pas toujours possible.

  5. #5
    Membre averti
    Homme Profil pro
    Ingénieur commercial
    Inscrit en
    Avril 2017
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur commercial

    Informations forums :
    Inscription : Avril 2017
    Messages : 46
    Par défaut
    Hello CosmoKnacki,

    Merci pour ces conseils. Je suis partie sur la piste de l'utilisation d'un .XML au lieu du .HTML.
    Pour cela j'ai ce fichier modèle Word dans lequel j'ai mis un champs conditonnel pour reconnaitre la variable NOM dans les balises du fichier XML:

    Nom : Capture d’écran 2019-07-11 à 09.58.29.png
Affichages : 664
Taille : 170,3 Ko
    Nom : Capture d’écran 2019-07-11 à 09.59.36.png
Affichages : 749
Taille : 294,0 Ko

    Dans le fichier XML, je retrouve bien mon texte "NOM" dans une balise de type "std". A ce stade je suis partie de du principe que les milliers d'heures passées à developper Word par les ingénieurs de Microsoft me garantissent que le fichier XML généré par Word est forcement sans erreur de format XML. Je suis peut être trop optimiste

    Nom : Capture d’écran 2019-07-11 à 10.02.15.png
Affichages : 670
Taille : 257,9 Ko

    Voici à quoi ressemble mon code maintenant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Extract data from Bonjour.xml
    $content = file_get_contents( dirname( __FILE__ ) . '/Bonjour.xml' );
      if ($content === false) echo "ERROR CANNOT READ file";
    //Extraction of <w:sdt> tags included in Word Template
    libxml_use_internal_errors(true);
    $dom = new DOMDocument();
    $dom->loadXML($content);
    		foreach ($dom->getElementsByTagNameNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 'sdt') as $element) {
        echo 'local name: ', $element->localName, ', prefix: ', $element->prefix, value: ', $element->nodeValue, "\n";
    }

    et ça fonctione voici ce que m'affiche la page web:

    Nom : Capture d’écran 2019-07-11 à 11.08.26.png
Affichages : 593
Taille : 28,8 Ko

    Encore merci beaucoup !

    Un dernier point, je remarque la fonction ne récupére pas tous les paramétres de la balise. En effet voici ce qui est contenu dans $element:

    Nom : Capture d’écran 2019-07-11 à 11.32.43.png
Affichages : 558
Taille : 178,6 Ko

    Voici le contenu du XML:
    Nom : Capture d’écran 2019-07-11 à 11.33.05.png
Affichages : 572
Taille : 91,1 Ko

    J'aimerai récupérer l'ID:
    <w:id w:val="950663817"/>

    Afin d'identifier de façon univoque la variable car 2 balises "sdt" pourraient avoir le même nom. Une idée pour cela ?

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Ah bah si tu peux réenregistrer le fichier sous forme XML, c'est effectivement l'idéal, donc fonce.

    Ne soit pas étonné de ne voir ni les attributs ni les nœuds enfants en faisant var_dump($element);, celui-ci ne donnera que les caractéristiques de l'objet DOMElement et pas la description détaillée de ses attributs XML ni de ses nœuds enfants quels qu'ils soient.

    Pour parvenir plus facilement à tes fins, tu peux t'intéresser au langage XPath (tutoriel nécessaire) via la class DOMXPath qui permet de faire des recherches ciblées dans l'arbre DOM, exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $xp = new DOMXPath($dom);
    $xp->registerNameSpace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); // permet de définir les préfixes utilisés dans les requêtes XPath
     
    $result = $xp->evaluate('string(//w:sdt/w:sdtPr/w:id/@val)');
     
    echo $result;
    (XPath n'est pas indispensable, on peut très bien s'en passer, mais dés lors qu'il s'agit de vérifier des relations de parenté, les fonctions classiques du DOM deviennent très lourdes à exploiter et nécessitent des boucles à n'en plus finir sur les enfants des enfants des enfants... de l'élément.)

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

Discussions similaires

  1. Récupérer les balises headings de la page html
    Par MisterLSC dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 06/04/2018, 12h24
  2. Réponses: 25
    Dernier message: 10/12/2011, 23h21
  3. Réponses: 2
    Dernier message: 09/12/2010, 21h03
  4. Comment récupérer les balises enfant ?
    Par souffle56 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 12/08/2010, 22h21
  5. [XML] HTML dns XML -> Récupérer les balises intérprétées comme du XML
    Par dacid dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 16/04/2010, 17h59

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