static function insertHTML($filename, $html, $placeholder = '%CONTENT%') { if (!strlen($html)) { return FALSE; } $xml = self::getXML($filename); if (!$xml) { trigger_error("Couldn't get Content XML from {$filename}"); return FALSE; } $dom = new DOMDocument(); $dom->loadXML($xml); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; // Find where to insert into the document $insertPoint = NULL; foreach ($dom->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'p') as $elt) { if (trim($elt->textContent) == $placeholder) { $insertPoint = $elt; break; } } if (NULL === $insertPoint) { trigger_error("Could not find {$placeholder} in a paragraph to insert the new content"); return FALSE; } $paraStyle = $insertPoint->getAttribute('text:style-name'); // ADD STYLES $styleData = array('JethroBold' => array('fo:font-weight' => 'bold'), 'JethroItalic' => array('fo:font-style' => 'italic'), 'JethroUnderline' => array('style:text-underline-style' => 'solid', 'style:text-underline-width' => 'auto', 'style:text-underline-color' => 'font-color'), 'JethroSmall' => array('fo:font-size' => '6pt')); $aStylesElt = $dom->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'automatic-styles')->item(0); foreach ($styleData as $styleName => $attrs) { $newStyle = $dom->createElement('style:style'); $newStyle->setAttribute('style:name', $styleName); if ($styleName == 'JethroSmall') { $newStyle->setAttribute('style:family', 'paragraph'); $newStyle->setAttribute('style:parent-style-name', $paraStyle); } else { $newStyle->setAttribute('style:family', 'text'); } $aStylesElt->appendChild($newStyle); $newTp = $dom->createElement('style:text-properties'); foreach ($attrs as $key => $val) { $newTp->setAttribute($key, $val); if (0 === strpos('fo:', $key)) { $newTp->setAttribute($key . '-asian', $val); $newTp->setAttribute($key . '-complex', $val); } } $newStyle->appendChild($newTp); } // ADD CONTENT $map = array('p' => array('text:p', array('text:style-name' => $paraStyle)), 'br' => array('text:line-break', array()), 'b' => array('text:span', array('text:style-name' => 'JethroBold')), 'strong' => array('text:span', array('text:style-name' => 'JethroBold')), 'i' => array('text:span', array('text:style-name' => 'JethroItalic')), 'em' => array('text:span', array('text:style-name' => 'JethroItalic')), 'u' => array('text:span', array('text:style-name' => 'JethroUnderline')), 'small' => array('text:p', array('text:style-name' => 'JethroSmall'))); for ($i = 1; $i <= 6; $i++) { $map['h' . $i] = array('text:h', array('text:outline-level' => $i)); } $input = strip_tags($html, '<' . implode('>,<', array_keys($map)) . '>'); $input = preg_replace('#[>]\\s+#', '>', $input); // strip space after tags which would cause funny indents $input = '<body>' . $input . '</body>'; $htmlDom = new DOMDocument(); $htmlDom->preserveWhiteSpace = false; $htmlDom->formatOutput = true; $htmlDom->loadHTML($input); $newTags = array(); foreach ($map as $from => $to) { list($newTag, $newAttrs) = $to; ODF_Tools::renameTags($htmlDom, $from, $newTag, $newAttrs, 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); $newTags[] = $newTag; } // Now we need to get the result XML text and load it into a real XML DOM, not an HTML one $fragmentXML = $htmlDom->saveXML(); $begin = strpos($fragmentXML, '<body>') + 6; $length = strpos($fragmentXML, '</body>') - $begin; $fragmentXML = '<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" office:version="1.2"> ' . substr($fragmentXML, $begin, $length) . '</office:document-content>'; $fragmentDom = new DOMDocument(); $fragmentDom->loadXML($fragmentXML); foreach ($fragmentDom->firstChild->childNodes as $newNode) { $newNew = $dom->importNode($newNode, true); $insertPoint->parentNode->insertBefore($newNew, $insertPoint); } $insertPoint->parentNode->removeChild($insertPoint); return ODF_Tools::setXML($filename, $dom->saveXML()); }
function mergeODT($source_file, $merged_file) { $xml_filename = 'content.xml'; require_once 'include/odf_tools.class.php'; $content = ODF_Tools::getXML($source_file, $xml_filename); if (empty($content)) { trigger_error('Could not find content within this ' . $extension . ' file'); return; } $HEADER_END = '</text:sequence-decls>'; $FOOTER_START = '</office:text>'; $middle_start_pos = strpos($content, $HEADER_END) + strlen($HEADER_END); $middle_end_pos = strpos($content, $FOOTER_START); if (NULL === $middle_start_pos || NULL === $middle_end_pos) { trigger_error('Cannot locate body content of the file'); return; } $middle_template = substr($content, $middle_start_pos, $middle_end_pos - $middle_start_pos); $header = substr($content, 0, $middle_start_pos); $footer = substr($content, $middle_end_pos); $merged_middle = ''; foreach ($this->getMergeData() as $id => $row) { if (empty($row)) { continue; } $this_middle = $middle_template; foreach ($row as $k => $v) { $this_middle = str_replace('%' . strtoupper($k) . '%', ODF_Tools::odfEntities(trim($v)), $this_middle); } $merged_middle .= $this_middle; } $merged_file = dirname($source_file) . '/jethro_merged_' . time() . session_id(); copy($source_file, $merged_file); ODF_Tools::setXML($merged_file, $header . $merged_middle . $footer, $xml_filename); }