Skip to content

Commit 50ae8f3

Browse files
committed
Merge pull request #83 from RomanSyroeshko/PHPWord#46
Ability to apply XSL style sheet to Template
2 parents 545cbc6 + 4c414c8 commit 50ae8f3

File tree

8 files changed

+184
-1
lines changed

8 files changed

+184
-1
lines changed

Classes/PHPWord/Template.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function __construct($strFilename)
6464
if ($this->_tempFileName !== false) {
6565
// Copy the source File to the temp File
6666
if (!copy($strFilename, $this->_tempFileName)) {
67-
throw new PHPWord_Exception('Could not copy the template from ' . $strFilename . ' to ' . $this->_tempFileName . '.');
67+
throw new PHPWord_Exception("Could not copy the template from {$strFilename} to {$this->_tempFileName}.");
6868
}
6969

7070
$this->_objZip = new ZipArchive();
@@ -75,6 +75,36 @@ public function __construct($strFilename)
7575
throw new PHPWord_Exception('Could not create temporary file with unique name in the default temporary directory.');
7676
}
7777
}
78+
79+
/**
80+
* Applies XSL style sheet to template's parts
81+
*
82+
* @param DOMDocument &$xslDOMDocument
83+
* @param array $xslOptions = array()
84+
* @param string $xslOptionsURI = ''
85+
*/
86+
public function applyXslStyleSheet(&$xslDOMDocument, $xslOptions = array(), $xslOptionsURI = '')
87+
{
88+
$processor = new \XSLTProcessor();
89+
90+
$processor->importStylesheet($xslDOMDocument);
91+
92+
if ($processor->setParameter($xslOptionsURI, $xslOptions) === false) {
93+
throw new \Exception('Could not set values for the given XSL style sheet parameters.');
94+
}
95+
96+
$xmlDOMDocument = new \DOMDocument();
97+
if ($xmlDOMDocument->loadXML($this->_documentXML) === false) {
98+
throw new \Exception('Could not load XML from the given template.');
99+
}
100+
101+
$xmlTransformed = $processor->transformToXml($xmlDOMDocument);
102+
if ($xmlTransformed === false) {
103+
throw new \Exception('Could not transform the given XML document.');
104+
}
105+
106+
$this->_documentXML = $xmlTransformed;
107+
}
78108

79109
/**
80110
* Set a Template value

Tests/PHPWord/TemplateTest.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
namespace PHPWord\Tests;
3+
4+
use PHPWord_Template;
5+
6+
/**
7+
* @coversDefaultClass PHPWord_Template
8+
*/
9+
class PHPWord_TemplateTest extends \PHPUnit_Framework_TestCase
10+
{
11+
/**
12+
* @covers ::applyXslStyleSheet
13+
* @test
14+
*/
15+
final public function testXslStyleSheetCanBeApplied()
16+
{
17+
$template = new PHPWord_Template(
18+
\join(
19+
\DIRECTORY_SEPARATOR,
20+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'with_table_macros.docx')
21+
)
22+
);
23+
24+
$xslDOMDocument = new \DOMDocument();
25+
$xslDOMDocument->load(
26+
\join(
27+
\DIRECTORY_SEPARATOR,
28+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'remove_tables_by_needle.xsl')
29+
)
30+
);
31+
32+
foreach (array('${employee.', '${scoreboard.') as $needle) {
33+
$template->applyXslStyleSheet($xslDOMDocument, array('needle' => $needle));
34+
}
35+
36+
$actualDocument = $template->save();
37+
$expectedDocument = \join(
38+
\DIRECTORY_SEPARATOR,
39+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'without_table_macros.docx')
40+
);
41+
42+
$actualZip = new \ZipArchive();
43+
$actualZip->open($actualDocument);
44+
$actualXml = $actualZip->getFromName('word/document.xml');
45+
if ($actualZip->close() === false) {
46+
throw new \Exception('Could not close zip file "' . $actualDocument . '".');
47+
}
48+
49+
$expectedZip = new \ZipArchive();
50+
$expectedZip->open($expectedDocument);
51+
$expectedXml = $expectedZip->getFromName('word/document.xml');
52+
if ($expectedZip->close() === false) {
53+
throw new \Exception('Could not close zip file "' . $expectedDocument . '".');
54+
}
55+
56+
$this->assertXmlStringEqualsXmlString($expectedXml, $actualXml);
57+
}
58+
59+
/**
60+
* @covers ::applyXslStyleSheet
61+
* @expectedException Exception
62+
* @expectedExceptionMessage Could not set values for the given XSL style sheet parameters.
63+
* @test
64+
*/
65+
final public function testXslStyleSheetCanNotBeAppliedOnFailureOfSettingParameterValue()
66+
{
67+
$template = new PHPWord_Template(
68+
\join(
69+
\DIRECTORY_SEPARATOR,
70+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'blank.docx')
71+
)
72+
);
73+
74+
$xslDOMDocument = new \DOMDocument();
75+
$xslDOMDocument->load(
76+
\join(
77+
\DIRECTORY_SEPARATOR,
78+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl')
79+
)
80+
);
81+
82+
/*
83+
* We have to use error control below, because XSLTProcessor::setParameter omits warning on failure.
84+
* This warning fails the test.
85+
*/
86+
@$template->applyXslStyleSheet($xslDOMDocument, array(1 => 'somevalue'));
87+
}
88+
89+
/**
90+
* @covers ::applyXslStyleSheet
91+
* @expectedException Exception
92+
* @expectedExceptionMessage Could not load XML from the given template.
93+
* @test
94+
*/
95+
final public function testXslStyleSheetCanNotBeAppliedOnFailureOfLoadingXmlFromTemplate()
96+
{
97+
$template = new PHPWord_Template(
98+
\join(
99+
\DIRECTORY_SEPARATOR,
100+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'corrupted_main_document_part.docx')
101+
)
102+
);
103+
104+
$xslDOMDocument = new \DOMDocument();
105+
$xslDOMDocument->load(
106+
\join(
107+
\DIRECTORY_SEPARATOR,
108+
array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl')
109+
)
110+
);
111+
112+
/*
113+
* We have to use error control below, because DOMDocument::loadXML omits warning on failure.
114+
* This warning fails the test.
115+
*/
116+
@$template->applyXslStyleSheet($xslDOMDocument);
117+
}
118+
}
4.96 KB
Binary file not shown.

Tests/_files/templates/blank.docx

3.7 KB
Binary file not shown.
Binary file not shown.
5.25 KB
Binary file not shown.

Tests/_files/xsl/passthrough.xsl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3+
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
4+
5+
<xsl:template match='@*|node()'>
6+
<xsl:copy>
7+
<xsl:apply-templates select='@*|node()'/>
8+
</xsl:copy>
9+
</xsl:template>
10+
11+
</xsl:stylesheet>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet
3+
version="1.0"
4+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5+
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
6+
7+
<xsl:template match='@*|node()'>
8+
<xsl:copy>
9+
<xsl:apply-templates select='@*|node()'/>
10+
</xsl:copy>
11+
</xsl:template>
12+
13+
<xsl:template match="//w:tbl">
14+
<xsl:choose>
15+
<xsl:when test="w:tr/w:tc/w:p/w:r/w:t[contains(., $needle)]"/>
16+
<xsl:otherwise>
17+
<xsl:copy>
18+
<xsl:apply-templates select='@*|node()'/>
19+
</xsl:copy>
20+
</xsl:otherwise>
21+
</xsl:choose>
22+
</xsl:template>
23+
24+
</xsl:stylesheet>

0 commit comments

Comments
 (0)