diff --git a/Classes/PHPWord/Template.php b/Classes/PHPWord/Template.php
index eb6e42d2..a1b26714 100755
--- a/Classes/PHPWord/Template.php
+++ b/Classes/PHPWord/Template.php
@@ -64,7 +64,7 @@ class PHPWord_Template
if ($this->_tempFileName !== false) {
// Copy the source File to the temp File
if (!copy($strFilename, $this->_tempFileName)) {
- throw new PHPWord_Exception('Could not copy the template from ' . $strFilename . ' to ' . $this->_tempFileName . '.');
+ throw new PHPWord_Exception("Could not copy the template from {$strFilename} to {$this->_tempFileName}.");
}
$this->_objZip = new ZipArchive();
@@ -75,6 +75,36 @@ class PHPWord_Template
throw new PHPWord_Exception('Could not create temporary file with unique name in the default temporary directory.');
}
}
+
+ /**
+ * Applies XSL style sheet to template's parts
+ *
+ * @param DOMDocument &$xslDOMDocument
+ * @param array $xslOptions = array()
+ * @param string $xslOptionsURI = ''
+ */
+ public function applyXslStyleSheet(&$xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '')
+ {
+ $processor = new \XSLTProcessor();
+
+ $processor->importStylesheet($xslDOMDocument);
+
+ if ($processor->setParameter($xslOptionsURI, $xslOptions) === false) {
+ throw new \Exception('Could not set values for the given XSL style sheet parameters.');
+ }
+
+ $xmlDOMDocument = new \DOMDocument();
+ if ($xmlDOMDocument->loadXML($this->_documentXML) === false) {
+ throw new \Exception('Could not load XML from the given template.');
+ }
+
+ $xmlTransformed = $processor->transformToXml($xmlDOMDocument);
+ if ($xmlTransformed === false) {
+ throw new \Exception('Could not transform the given XML document.');
+ }
+
+ $this->_documentXML = $xmlTransformed;
+ }
/**
* Set a Template value
diff --git a/Tests/PHPWord/TemplateTest.php b/Tests/PHPWord/TemplateTest.php
new file mode 100644
index 00000000..1cc30639
--- /dev/null
+++ b/Tests/PHPWord/TemplateTest.php
@@ -0,0 +1,118 @@
+load(
+ \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'remove_tables_by_needle.xsl')
+ )
+ );
+
+ foreach (array('${employee.', '${scoreboard.') as $needle) {
+ $template->applyXslStyleSheet($xslDOMDocument, array('needle' => $needle));
+ }
+
+ $actualDocument = $template->save();
+ $expectedDocument = \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'without_table_macros.docx')
+ );
+
+ $actualZip = new \ZipArchive();
+ $actualZip->open($actualDocument);
+ $actualXml = $actualZip->getFromName('word/document.xml');
+ if ($actualZip->close() === false) {
+ throw new \Exception('Could not close zip file "' . $actualDocument . '".');
+ }
+
+ $expectedZip = new \ZipArchive();
+ $expectedZip->open($expectedDocument);
+ $expectedXml = $expectedZip->getFromName('word/document.xml');
+ if ($expectedZip->close() === false) {
+ throw new \Exception('Could not close zip file "' . $expectedDocument . '".');
+ }
+
+ $this->assertXmlStringEqualsXmlString($expectedXml, $actualXml);
+ }
+
+ /**
+ * @covers ::applyXslStyleSheet
+ * @expectedException Exception
+ * @expectedExceptionMessage Could not set values for the given XSL style sheet parameters.
+ * @test
+ */
+ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue()
+ {
+ $template = new PHPWord_Template(
+ \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'blank.docx')
+ )
+ );
+
+ $xslDOMDocument = new \DOMDocument();
+ $xslDOMDocument->load(
+ \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl')
+ )
+ );
+
+ /*
+ * We have to use error control below, because XSLTProcessor::setParameter omits warning on failure.
+ * This warning fails the test.
+ */
+ @$template->applyXslStyleSheet($xslDOMDocument, array(1 => 'somevalue'));
+ }
+
+ /**
+ * @covers ::applyXslStyleSheet
+ * @expectedException Exception
+ * @expectedExceptionMessage Could not load XML from the given template.
+ * @test
+ */
+ final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplate()
+ {
+ $template = new PHPWord_Template(
+ \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'corrupted_main_document_part.docx')
+ )
+ );
+
+ $xslDOMDocument = new \DOMDocument();
+ $xslDOMDocument->load(
+ \join(
+ \DIRECTORY_SEPARATOR,
+ array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl')
+ )
+ );
+
+ /*
+ * We have to use error control below, because DOMDocument::loadXML omits warning on failure.
+ * This warning fails the test.
+ */
+ @$template->applyXslStyleSheet($xslDOMDocument);
+ }
+}
\ No newline at end of file
diff --git a/Tests/_files/documents/without_table_macros.docx b/Tests/_files/documents/without_table_macros.docx
new file mode 100644
index 00000000..e4e9767f
Binary files /dev/null and b/Tests/_files/documents/without_table_macros.docx differ
diff --git a/Tests/_files/templates/blank.docx b/Tests/_files/templates/blank.docx
new file mode 100644
index 00000000..071b7f35
Binary files /dev/null and b/Tests/_files/templates/blank.docx differ
diff --git a/Tests/_files/templates/corrupted_main_document_part.docx b/Tests/_files/templates/corrupted_main_document_part.docx
new file mode 100644
index 00000000..69712525
Binary files /dev/null and b/Tests/_files/templates/corrupted_main_document_part.docx differ
diff --git a/Tests/_files/templates/with_table_macros.docx b/Tests/_files/templates/with_table_macros.docx
new file mode 100644
index 00000000..cd5ed6ce
Binary files /dev/null and b/Tests/_files/templates/with_table_macros.docx differ
diff --git a/Tests/_files/xsl/passthrough.xsl b/Tests/_files/xsl/passthrough.xsl
new file mode 100644
index 00000000..4ab21dd7
--- /dev/null
+++ b/Tests/_files/xsl/passthrough.xsl
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Tests/_files/xsl/remove_tables_by_needle.xsl b/Tests/_files/xsl/remove_tables_by_needle.xsl
new file mode 100644
index 00000000..1a7b1369
--- /dev/null
+++ b/Tests/_files/xsl/remove_tables_by_needle.xsl
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+