【问题标题】:Read image and text from docx using PHP DOM Document使用 PHP DOM Document 从 docx 读取图像和文本
【发布时间】:2020-04-28 00:31:36
【问题描述】:

我有一个 Word docx 文件。它有一个带有rowscolumns 的表。我创建了一个 PHP 代码,当我在运行 PHP 文件后进行检查时,它以 XML 格式获取。我想printf php 页面上的文字和图片。

以下是使用 DOM 文档的 php 文件从 word 中读取文本时的外观:

这是我的 Word 文件 - we.tl/t-tGddnyasKj

到目前为止的 PHP 代码:

<?php  

    #extract.php
   function pre( $data=false, $header=false, $tag='h1' ){
        $title = $header ? sprintf('<'.$tag.'>%s</'.$tag.'>',$header) : '';
        printf('%s<pre>%s</pre>',$title,print_r($data,1));
    }


    $document = 'sample.docx';


    function process_word_docx( $filename ){
        $zip = new ZipArchive;
        if( true === $zip->open( $filename ) ) {
            for( $i=0; $i < $zip->numFiles; $i++ ) {
                $obj=(object)$zip->statIndex( $i );
                if( $obj->name=='word/document.xml' ){
                    $xml=$zip->getFromIndex( $i );

                    libxml_use_internal_errors( true );
                    $dom=new DOMDocument('1.0','utf-8');
                    $dom->validateOnParse=false;
                    $dom->recover=true;
                    $dom->strictErrorChecking=false;
                    $dom->loadXML( $xml );
                    libxml_clear_errors();

                    $xp=new DOMXPath( $dom );
                    $xp->registerNamespace('ve','http://schemas.openxmlformats.org/markup-compatibility/2006');
                    $xp->registerNamespace('r','http://schemas.openxmlformats.org/officeDocument/2006/relationships');
                    $xp->registerNamespace('m','http://schemas.openxmlformats.org/officeDocument/2006/math');
                    $xp->registerNamespace('wp','http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing');
                    $xp->registerNamespace('w','http://schemas.openxmlformats.org/wordprocessingml/2006/main');

                    pre( $xml );

                }
            }
        }
    }
    process_word_docx( $document );


?>

如何在 PHP 页面上打印文本和图像?

【问题讨论】:

    标签: php


    【解决方案1】:

    在昨天的扩展讨论之后,我继续修改函数并得出以下结果 - 您应该能够从中提取所需的信息。您声明需要保存图像并将图像名称和其他文本写入数据库 - 结果数组具有相关内容。

    我发现像这样将docx 文件加载到 DOMDocument 实例中会导致 DOM 解析器对命名空间属性做一些奇怪的事情——它们显示为小写,但不能以小写形式查询,除非整个 xml 字符串以小写形式呈现。另一种方法是煞费苦心地为 XPath 查询中使用的各种标签找到正确的驼峰式。

    <?php   
    
        define('br','<br />');
    
        #extract.php
        function pre( $data=false, $header=false, $tag='h1' ){
            $title = $header ? sprintf('<'.$tag.'>%s</'.$tag.'>',$header) : '';
            printf('%s<pre>%s</pre>',$title,print_r($data,1)); 
        }
    
    
        $document = 'sample.docx';
    
    
    
        function getparent( $n, $tag ){
            while( $n && $n->nodeType==XML_ELEMENT_NODE && $n->tagName!=$tag ){
                $n=$n->parentNode;
            }
            return $n;
        }
    
    
        function process_word_docx( $filename ){
            $data=[ 'start' => microtime( true ),'names'=>[] ];
            $paths=[];
    
            $zip=new ZipArchive;
    
    
            if( true === $zip->open( $filename ) ) {
                for( $i=0; $i < $zip->numFiles; $i++ ) {
                    $obj=(object)$zip->statIndex( $i );
    
                    if( $obj->name=='word/document.xml' ){
    
                        $xml=$zip->getFromIndex( $i );
    
                        $data['position']=$obj->index;
                        $data['xml-size']=$obj->size;
                        $data['created']=$obj->mtime;
                        $data['compression-method']=$obj->comp_method;
    
    
    
                        libxml_use_internal_errors( true );
                        $dom=new DOMDocument('1.0','utf-8');
                        $dom->validateOnParse=false;
                        $dom->recover=true;
                        $dom->strictErrorChecking=false;
                        $dom->loadXML( strtolower( $xml ) );
                        libxml_clear_errors();
    
    
    
                        $xp=new DOMXPath( $dom );
                        /* none of these namespace uris exist */
                        $xp->registerNamespace('ve','http://schemas.openxmlformats.org/markup-compatibility/2006');
                        $xp->registerNamespace('r','http://schemas.openxmlformats.org/officeDocument/2006/relationships');
                        $xp->registerNamespace('m','http://schemas.openxmlformats.org/officeDocument/2006/math');
                        $xp->registerNamespace('wp','http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing');
                        $xp->registerNamespace('w','http://schemas.openxmlformats.org/wordprocessingml/2006/main');
                        $xp->registerNamespace('pic','http://schemas.openxmlformats.org/drawingml/2006/picture');
                        $xp->registerNamespace('a','http://schemas.openxmlformats.org/drawingml/2006/main');
                        /* this/these exist */
                        $xp->registerNamespace('wne','http://schemas.microsoft.com/office/word/2006/wordml');
    
    
                        /* find tables */
                        $col=$xp->query( '//w:tbl//w:tr' );
                        if( $col->length > 0 ){
                            foreach( $col as $row => $tr ){
    
                                /* Count the cells on each row */
                                $expr='count( w:tc )';
                                $cellcount=$xp->evaluate( $expr, $tr );
    
                                if( $cellcount > 0 ){
                                    /* find all the table cells for this row */
                                    $expr='w:tc';
                                    $cells=$xp->query( $expr, $tr );
    
                                    /* Are there any images in this row */
                                    $expr='count(//pic:cnvpr)';
                                    $qty=$xp->evaluate( $expr, $tr );
    
    
                                    /* There are images */
                                    if( $qty > 0 ){
    
                                        $expr='w:tc//w:drawing//a:graphic//pic:pic//pic:nvpicpr/pic:cnvpr';
                                        $wpcol=$xp->query( $expr, $tr );
    
                                        if( $wpcol->length > 0 ){
                                            foreach( $wpcol as $index=> $node ){
                                                /* navigate up the DOM tree until we find the table cell tag */
                                                $oCell = getparent( $node, 'w:tc' );
    
                                                /* Find the name of the image */
                                                $name = $node->getAttribute('name');
                                                $data['names'][]=$name;
    
                                                /* get the text in the current row */
                                                $text = ucfirst( $tr->textContent ) ?: ' - EMPTY -';
    
                                                /* find the cell index for the row */
                                                foreach( $cells as $index => $cell ){
                                                    if( $cell === $oCell )break;
                                                }
    
                                                /* prepare payload */
                                                if( $wpcol->length==1 ){
                                                    $data['statistics'][ $row ]=array(
                                                        'text'      =>  $text,
                                                        'name'      =>  $name,
                                                        'column'    =>  $index
                                                    );
                                                } else {
                                                    /* multiple images on this row - multiple images can be within a single cell */
                                                    $data['statistics'][ $row ][ $index ][]=array(
                                                        'text'      =>  $text,
                                                        'name'      =>  $name,
                                                        'column'    =>  $index
                                                    );
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }else{
                        if( preg_match( '([^\s]+(\.(?i)(jpg|jpeg|png|gif|bmp))$)', $obj->name ) ) {
                            $paths[ $obj->name ]=base64_encode( $zip->getFromIndex( $i ) );
                        }
                    }
                }
            }
            /* finalise statistics */
            $data['count']=$qty;
            $data['end']=microtime( true );
            $data['time']=$data['end'] - $data['start'];
            $data['total-size']=filesize( $filename );
            $data['paths']=$paths;
    
            /* return payload */
            return $data;
        }
    
    
    
        $data=process_word_docx( $document );
        pre( $data );
    
    ?>
    

    【讨论】:

    • 嗨,谢谢,我现在可以清楚地看到这一点,当我运行上面的代码时,它没有在 word\media\.. 中生成图像,你注意到代码了吗 - 它应该在生成图像时在数组中给出相同的名称,以便建立连接
    • 这可以构成保存图像的脚本的基础(请参阅先前的答案以了解如何),名称差异是单词的一个因素〜不确定如何/为什么
    • 我需要使用旧脚本中的代码来生成图像吗?但是我又该如何关联,保存的图像的名称与获取的名称不同,如果此脚本可以生成并关联,那么我就完成了
    • 我们需要将生成的图片和数组中的名字关联起来,请指导带我回家
    • Word 似乎为图像分配了通用名称 - 我不知道为什么/如何工作。 docx 父文件中有几个文件——其中一个描述了主 xml/word 文档中元素的关系。检查每一个都不是一件容易的事 - 一旦可以理解关系,那么它应该很容易
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多