2016-07-15 45 views
0

Wie kann ich docx-Inhalte lesen und alle Tags entfernen, aber diese unten behalten?PHP docx Datei Inhalt lesen, aber Zeilenumbrüche, kursiv, unterstrichen und fett?

  1. Bold
  2. Italic
  3. Unterstrichen
  4. New Line

Unten ist mein Code, den ich von den anderen Antworten bekommen:

//FUNCTION :: read a docx file and return the string 
// http://stackoverflow.com/questions/4587216/how-can-i-convert-a-docx-document-to-html-using-php 
// https://www.jackreichert.com/2012/11/how-to-convert-docx-to-html/ 
function readDocx($filePath) { 
    // Create new ZIP archive 
    $zip = new ZipArchive; 
    $dataFile = 'word/document.xml'; 
    // Open received archive file 
    if (true === $zip->open($filePath)) { 
     // If done, search for the data file in the archive 
     if (($index = $zip->locateName($dataFile)) !== false) { 
      // If found, read it to the string 
      $data = $zip->getFromIndex($index); 
      // Close archive file 
      $zip->close(); 
      // Load XML from a string 
      // Skip errors and warnings 
      $xml = DOMDocument::loadXML($data, LIBXML_NOENT | LIBXML_XINCLUDE | LIBXML_NOERROR | LIBXML_NOWARNING); 
      // Return data without XML formatting tags 
      $xmldata = $xml->saveXML(); 
      // </w:p> is what word uses to mark the end of a paragraph. E.g. 
      // <w:p>This is a paragraph.</w:p> 
      // <w:p>And a second one.</w:p> 
      // http://stackoverflow.com/questions/5607594/find-linebreaks-in-a-docx-file-using-php 
      $xmldata = str_replace("</w:p>", "\r\n", $xmldata); 
      $xmldata = str_replace("<w:i/>", "<i>", $xmldata); 

      $contents = explode('\n',strip_tags($xmldata, "<i>")); 
      $text = ''; 
      foreach($contents as $i=>$content) { 
       $text .= $contents[$i]; 
      } 
      return $text; 
     } 
     $zip->close(); 
    } 
    // In case of failure return empty string 
    return ""; 
} 

$filePath = 'sample.docx'; 
$string = readDocx($filePath); 
var_dump($string); 

Bisher habe ich nur verwalten Zeilenumbrüche, aber nicht den Rest:

$xmldata = str_replace("</w:p>", "\r\n", $xmldata); 
$xmldata = str_replace("<w:i/>", "<i>", $xmldata); // will get <i>Hello World <-- no closing i 

Irgendwelche Ideen?

EDIT:

$xmldata = preg_replace("/<w\:i\/>(.*?)<\/w\:r>/is", "<i>$1</i>", $xmldata); 
$xmldata = preg_replace("/<w\:b\/>(.*?)<\/w\:r>/is", "<b>$1</b>", $xmldata); 
$xmldata = preg_replace("/<w\:u (.*?)\/>(.*?)<\/w\:r>/is", "<u>$2</u>", $xmldata); 

Aber die oben genannten Lösungen haben Fehler, weil zum Beispiel:

<w:r><w:t xml:space="preserve"><w:i/>Hello</w:t></w:r><w:r><w:t xml:space="preserve"> World</w:t></w:r> 

Sie werden feststellen, ich <w:i/> und <\/w\:r> bin ersetzt werden, weil <w:i/> nicht paaren hat.

Irgendwelche besseren Lösungen?

Antwort

0

Tags Strippen keine gute Art und Weise ist, weil mit Ihrer aktuellen Lösung bekommt man nicht das Ende der Formatierung - Sie sollten darüber nachdenken, xml Interpretation statt

die anderen Tags, die Sie für die Suche sind <w:b/> (fett) und <w:u ...> (unterstrichen)

+0

bitte über meine bearbeiten sehen. Vielen Dank. – laukok

0

ich habe diese Lösungen - es ist hässlich, aber es funktioniert:

 $xmldata = 
        '<w:r> 
     <w:rPr> 
     <w:u/> 
     <w:b/> 
     <w:i/> 
     </w:rPr> 
     <w:t>I feel that there is much to be said for the Celtic belief that the souls of those whom we have lost are held captive in some inferior being...</w:t> 
     </w:r>'; 
     // </w:p> is what word uses to mark the end of a paragraph. E.g. 
     // <w:p>This is a paragraph.</w:p> 
     // <w:p>And a second one.</w:p> 
     // http://stackoverflow.com/questions/5607594/find-linebreaks-in-a-docx-file-using-php 
     // http://officeopenxml.com/WPtext.php 
     $xmldata = str_replace("</w:p>", "\r\n", $xmldata); 
     $xmldata = preg_replace("/<w\:i\/>(.*?)<w:t(.*?)>(.*?)<\/w\:t>/is", "<w:i/>$1<w:t$2><i>$3</i></w:t>", $xmldata); 
     $xmldata = preg_replace("/<w\:b\/>(.*?)<w:t(.*?)>(.*?)<\/w\:t>/is", "<w:b/>$1<w:t$2><b>$3</b></w:t>", $xmldata); 
     $xmldata = preg_replace("/<w\:u(.*?)\/>(.*?)<w:t(.*?)>(.*?)<\/w\:t>/is", "<w:u$1/>$2<w:t$3><u>$4</u></w:t>", $xmldata); 

Ausgang:

<u><b><i>I feel that there is much to be said for the Celtic belief that the souls of those whom we have lost are held captive in some inferior being...</i></b></u> 
1

ich eine Notwendigkeit dieser str_repalce() und explode() Funktionen nicht daher sehe ich einen einzigen strip_tags() tun:

$contents = strip_tags($xmldata, '<w:p><w:u><w:i><w:b>'); 

Inzwischen Sie sicher sind, alle gewünschten Tags erhalten bleiben. Einen weiteren Schritt sollten wir <w:*>-Tags mit ihren entsprechenden HTML-Tags ersetzen:

$contents = preg_replace("/(<(\/?)w:(.)[^>]*>)\1*/", "<$2$3>", $contents); 

Wir haben nur HTML-Tags mit einem Zeichen in ihren Namen <p>, <b>, <i>, <u> ihre Namen so die Erfassung so einfach ist wie mit Punkterfassungsgruppe:

(    # (1 start) 
     <    # Match XML opening tag character   
     (\/?)  # (2) Match if it is going to be an ending tag 
     w:   # Literal `w:` 
     (.)   # (3) Match b,p,u,i 
     [^>]* >  # Up to closing tag character 
)    # (1 end) 
\1*    # Match if latter group repeats 

ich hatte für gleiche abgestimmt Tags \1* zu überprüfen, weil ich es hoch herausgefunden p Ossibilität zu passieren.Wenn unsere docx-Datei enthält drei Zeilen wie unten:

Bold

Italic

Normale

Dann an dieser Stelle unsere Ausgabe ähnelt dies:

<p><b><b>Bold</p><p><i><i>Italic</p><p>Normal</p> 

Aber wie Sie sehen können, haben wir ungepaarte doppelte Tags, die n sind überhaupt nicht gut. Wir sollten unser Dokument aufräumen. Aber wie?

  1. von PHP Tidy Erweiterung
  2. unsere HTML DOMDocument in ein Objekt laden

Obwohl PHP Tidy für diese Art von Arbeit ist sehr gut, ich DOMDocument besser geeignet dafür unsere Aufgabe gefunden:

Wir haben zwei verwandte Flags gesetzt, da wir HTML DOCTYPE sowie <html>/nicht benötigenTags.

an dieser Stelle Unsere Ausgabe:

<p><b><b>Bold</b></b><p><i><i>Italic</i></i></p><p>Normal</p></p> 

Die gute Nachricht ist, jetzt haben wir paird-Tags, aber es könnte eine schlechte Nachricht sein, dass wir unnötig geöffnet Tags haben:

<p><b><b>Bold</b></b><p><i><i>Italic</i></i></p><p>Normal</p></p> 
^^    ^^ 

Für eine Arbeits Lösung um das Entfernen von zusätzlichen Öffnung Tags, schrieb ich eine andere RegEx:

$contents = preg_replace('~<([ibu])>(?=(?:\s*<[ibu]>\s*)*?<\1>)|</([ibu])>(?=(?:\s*</?[ibu]>\s*)*?</?\2>)|<p></p>~s', "", $contents); 

Was es tun wird kann werde hier zu sehen:

<         # Match an opening tag 
([ibu])       # (1) Any type except `p` 
>         # Up to closing character 
(?=        # Which is immediately followed by 
     (?: \s* <[ibu]> \s*)*?  # Another opening tag (or nothing) 
     <\1>      # And then its own closing tag. 
)         # End of lookahead 
|         # Or match 
</         # A closing tag 
([ibu])       # (2) Any type except `p` 
>         # Up to closing character 
(?=        # Which is immediately followed by 
     (?: \s* </ [ibu] > \s*)*? # Another closing tag (or nothing) 
     </? \2 >      # And then the same closing tag 
)         # End of lookahead 
|         # Or match 
<p></p>       # Empty <p> tags 

Jetzt haben wir die richtige Ausgabe:

<p><b>Bold</b><p><i>Italic</i></p><p>Normal</p></p> 

alles Putting zusammen:

<?php 

function readDocx($filePath) { 
    // Create new ZIP archive 
    $zip = new ZipArchive; 
    $dataFile = 'word/document.xml'; 
    // Open received archive file 
    if (true === $zip->open($filePath)) { 
     // If done, search for the data file in the archive 
     if (($index = $zip->locateName($dataFile)) !== false) { 
      $data = $zip->getFromIndex($index); 
      $zip->close(); 

      $dom = new DOMDocument; 
      $dom->loadXML($data, LIBXML_NOENT 
       | LIBXML_XINCLUDE 
       | LIBXML_NOERROR 
       | LIBXML_NOWARNING); 

      $xmldata = $dom->saveXML(); 

      $contents = strip_tags($xmldata, '<w:p><w:u><w:i><w:b>'); 
      $contents = preg_replace("/(<(\/?)w:(.)[^>]*>)\1*/", "<$2$3>", $contents); 

      $dom = new DOMDocument; 
      @$dom->loadHTML($contents, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 
      $contents = $dom->saveHTML(); 

      $contents = preg_replace('~<([ibu])>(?=(?:\s*<[ibu]>\s*)*?<\1>)|</([ibu])>(?=(?:\s*</[ibu]>\s*)*?</?\2>)|<p></p>~s', "", $contents); 

      return $contents; 
     } 
     $zip->close(); 
    } 
    // In case of failure return empty string 
    return ""; 
} 

$filePath = 'sample.docx'; 
$string = readDocx($filePath); 
echo $string;