/** * Read meta.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @return void * @todo Process property type */ public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $docProps = $phpWord->getDocInfo(); $metaNode = $xmlReader->getElement('office:meta'); // Standard properties $properties = array('title' => 'dc:title', 'subject' => 'dc:subject', 'description' => 'dc:description', 'keywords' => 'meta:keyword', 'creator' => 'meta:initial-creator', 'lastModifiedBy' => 'dc:creator'); foreach ($properties as $property => $path) { $method = "set{$property}"; $propertyNode = $xmlReader->getElement($path, $metaNode); if ($propertyNode !== null && method_exists($docProps, $method)) { $docProps->{$method}($propertyNode->nodeValue); } } // Custom properties $propertyNodes = $xmlReader->getElements('meta:user-defined', $metaNode); foreach ($propertyNodes as $propertyNode) { $property = $xmlReader->getAttribute('meta:name', $propertyNode); // Set category, company, and manager property if (in_array($property, array('Category', 'Company', 'Manager'))) { $method = "set{$property}"; $docProps->{$method}($propertyNode->nodeValue); // Set other custom properties } else { $docProps->setCustomProperty($property, $propertyNode->nodeValue); } } }
/** * Read (footnotes|endnotes).xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @return void */ public function read(PhpWord $phpWord) { $getMethod = "get{$this->collection}"; $collection = $phpWord->{$getMethod}()->getItems(); $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $nodes = $xmlReader->getElements('*'); if ($nodes->length > 0) { foreach ($nodes as $node) { $id = $xmlReader->getAttribute('w:id', $node); $type = $xmlReader->getAttribute('w:type', $node); // Avoid w:type "separator" and "continuationSeparator" // Only look for <footnote> or <endnote> without w:type attribute if (is_null($type) && isset($collection[$id])) { $element = $collection[$id]; $pNodes = $xmlReader->getElements('w:p/*', $node); foreach ($pNodes as $pNode) { $this->readRun($xmlReader, $pNode, $element, $this->collection); } $addMethod = "add{$this->element}"; $phpWord->{$addMethod}($element); } } } }
/** * Read all relationship files * * @param string $docFile * @return array */ private function readRelationships($docFile) { $rels = array(); $xmlFile = 'META-INF/manifest.xml'; $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($docFile, $xmlFile); $nodes = $xmlReader->getElements('manifest:file-entry'); foreach ($nodes as $node) { $type = $xmlReader->getAttribute('manifest:media-type', $node); $target = $xmlReader->getAttribute('manifest:full-path', $node); $rels[] = array('type' => $type, 'target' => $target); } return $rels; }
/** * Read content.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @return void */ public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $nodes = $xmlReader->getElements('office:body/office:text/*'); if ($nodes->length > 0) { $section = $phpWord->addSection(); foreach ($nodes as $node) { // $styleName = $xmlReader->getAttribute('text:style-name', $node); switch ($node->nodeName) { case 'text:h': // Heading $depth = $xmlReader->getAttribute('text:outline-level', $node); $section->addTitle($node->nodeValue, $depth); break; case 'text:p': // Paragraph $section->addText($node->nodeValue); break; case 'text:list': // List $listItems = $xmlReader->getElements('text:list-item/text:p', $node); foreach ($listItems as $listItem) { // $listStyleName = $xmlReader->getAttribute('text:style-name', $listItem); $section->addListItem($listItem->nodeValue, 0); } break; } } } }
/** * Read styles.xml. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @return void */ public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $nodes = $xmlReader->getElements('w:style'); if ($nodes->length > 0) { foreach ($nodes as $node) { $type = $xmlReader->getAttribute('w:type', $node); $name = $xmlReader->getAttribute('w:styleId', $node); if (is_null($name)) { $name = $xmlReader->getAttribute('w:val', $node, 'w:name'); } preg_match('/Heading(\\d)/', $name, $headingMatches); // $default = ($xmlReader->getAttribute('w:default', $node) == 1); switch ($type) { case 'paragraph': $paragraphStyle = $this->readParagraphStyle($xmlReader, $node); $fontStyle = $this->readFontStyle($xmlReader, $node); if (!empty($headingMatches)) { $phpWord->addTitleStyle($headingMatches[1], $fontStyle, $paragraphStyle); } else { if (empty($fontStyle)) { if (is_array($paragraphStyle)) { $phpWord->addParagraphStyle($name, $paragraphStyle); } } else { $phpWord->addFontStyle($name, $fontStyle, $paragraphStyle); } } break; case 'character': $fontStyle = $this->readFontStyle($xmlReader, $node); if (!empty($fontStyle)) { $phpWord->addFontStyle($name, $fontStyle); } break; case 'table': $tStyle = $this->readTableStyle($xmlReader, $node); if (!empty($tStyle)) { $phpWord->addTableStyle($name, $tStyle); } break; } } } }
/** * Read custom document properties. * * @param \PhpOffice\PhpWord\PhpWord $phpWord * @return void */ public function read(PhpWord $phpWord) { $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $docProps = $phpWord->getDocInfo(); $nodes = $xmlReader->getElements('*'); if ($nodes->length > 0) { foreach ($nodes as $node) { $propertyName = $xmlReader->getAttribute('name', $node); $attributeNode = $xmlReader->getElement('*', $node); $attributeType = $attributeNode->nodeName; $attributeValue = $attributeNode->nodeValue; $attributeValue = DocInfo::convertProperty($attributeValue, $attributeType); $attributeType = DocInfo::convertPropertyType($attributeType); $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType); } } }
/** * Read style definition * * @param \PhpOffice\Common\XMLReader $xmlReader * @param \DOMElement $parentNode * @param array $styleDefs * @ignoreScrutinizerPatch * @return array */ protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = null, $styleDefs = array()) { $styles = array(); foreach ($styleDefs as $styleProp => $styleVal) { @(list($method, $element, $attribute, $expected) = $styleVal); if ($xmlReader->elementExists($element, $parentNode)) { $node = $xmlReader->getElement($element, $parentNode); // Use w:val as default if no attribute assigned $attribute = $attribute === null ? 'w:val' : $attribute; $attributeValue = $xmlReader->getAttribute($attribute, $node); $styleValue = $this->readStyleDef($method, $attributeValue, $expected); if ($styleValue !== null) { $styles[$styleProp] = $styleValue; } } } return $styles; }
/** * Read numbering level definition from w:abstractNum and w:num * * @param \PhpOffice\Common\XMLReader $xmlReader * @param \DOMElement $subnode * @param integer $levelId * @return array */ private function readLevel(XMLReader $xmlReader, \DOMElement $subnode, $levelId) { $level = array(); $level['level'] = $levelId; $level['start'] = $xmlReader->getAttribute('w:val', $subnode, 'w:start'); $level['format'] = $xmlReader->getAttribute('w:val', $subnode, 'w:numFmt'); $level['restart'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlRestart'); $level['suffix'] = $xmlReader->getAttribute('w:val', $subnode, 'w:suff'); $level['text'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlText'); $level['alignment'] = $xmlReader->getAttribute('w:val', $subnode, 'w:lvlJc'); $level['tab'] = $xmlReader->getAttribute('w:pos', $subnode, 'w:pPr/w:tabs/w:tab'); $level['left'] = $xmlReader->getAttribute('w:left', $subnode, 'w:pPr/w:ind'); $level['hanging'] = $xmlReader->getAttribute('w:hanging', $subnode, 'w:pPr/w:ind'); $level['font'] = $xmlReader->getAttribute('w:ascii', $subnode, 'w:rPr/w:rFonts'); $level['hint'] = $xmlReader->getAttribute('w:hint', $subnode, 'w:rPr/w:rFonts'); foreach ($level as $key => $value) { if (is_null($value)) { unset($level[$key]); } } return $level; }
/** * Get relationship array * * @param string $docFile * @param string $xmlFile * @param string $targetPrefix * @return array */ private function getRels($docFile, $xmlFile, $targetPrefix = '') { $metaPrefix = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/'; $officePrefix = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/'; $rels = array(); $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($docFile, $xmlFile); $nodes = $xmlReader->getElements('*'); foreach ($nodes as $node) { $rId = $xmlReader->getAttribute('Id', $node); $type = $xmlReader->getAttribute('Type', $node); $target = $xmlReader->getAttribute('Target', $node); // Remove URL prefixes from $type to make it easier to read $type = str_replace($metaPrefix, '', $type); $type = str_replace($officePrefix, '', $type); $docPart = str_replace('.xml', '', $target); // Do not add prefix to link source if (!in_array($type, array('hyperlink'))) { $target = $targetPrefix . $target; } // Push to return array $rels[$rId] = array('type' => $type, 'target' => $target, 'docPart' => $docPart); } ksort($rels); return $rels; }
/** * Read w:p node. * * @param \PhpOffice\Common\XMLReader $xmlReader * @param \DOMElement $node * @param \PhpOffice\PhpWord\Element\Section &$section * @return void * * @todo <w:lastRenderedPageBreak> */ private function readWPNode(XMLReader $xmlReader, \DOMElement $node, Section &$section) { // Page break if ($xmlReader->getAttribute('w:type', $node, 'w:r/w:br') == 'page') { $section->addPageBreak(); // PageBreak } // Paragraph $this->readParagraph($xmlReader, $node, $section); // Section properties if ($xmlReader->elementExists('w:pPr/w:sectPr', $node)) { $sectPrNode = $xmlReader->getElement('w:pPr/w:sectPr', $node); if ($sectPrNode !== null) { $this->readWSectPrNode($xmlReader, $sectPrNode, $section); } $section = $this->phpWord->addSection(); } }