* @author Kornel LesiĆski
* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
* @version SVN: $Id: XmlParserTest.php 907 2010-06-14 13:50:15Z kornel $
* @link http://phptal.org/
*/
class XmlParserTest extends PHPTAL_TestCase
{
public function testSimpleParse()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseFile($builder = new MyDocumentBuilder(), 'input/xml.01.xml')->getResult();
$expected = trim(join('', file('input/xml.01.xml')));
$this->assertEquals($expected, $builder->result);
$this->assertEquals(7, $builder->elementStarts);
$this->assertEquals(7, $builder->elementCloses);
}
public function testXMLStylesheet()
{
$tpl = $this->newPHPTAL();
$tpl->baz = 'quz';
$tpl->setSource('
');
$this->assertXMLEquals('
', $tpl->execute());
}
public function testPHPBlocksNotInterpolated()
{
$tpl = $this->newPHPTAL();
$tpl->setSource('');
$this->assertEquals('${baz}', $tpl->execute());
}
public function testCharactersBeforeBegining()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try {
$parser->parseFile($builder = new MyDocumentBuilder(), 'input/xml.02.xml')->getResult();
$this->assertTrue( false );
}
catch (Exception $e)
{
$this->assertTrue( true );
}
}
public function testAllowGtAndLtInTextNodes()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseFile($builder = new MyDocumentBuilder(), 'input/xml.03.xml')->getResult();
$this->assertEquals(normalize_html_file('output/xml.03.xml'), normalize_html($builder->result));
$this->assertEquals(3, $builder->elementStarts);
$this->assertEquals(3, $builder->elementCloses);
// a '<' character withing some text data make the parser call 2 times
// the onElementData() method
$this->assertEquals(7, $builder->datas);
}
/**
* @expectedException PHPTAL_ParserException
*/
public function testRejectsInvalidAttributes1()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseString($builder = new MyDocumentBuilder(), '')->getResult();
$this->fail($builder->result);
}
/**
* @expectedException PHPTAL_ParserException
*/
public function testRejectsInvalidAttributes2()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseString($builder = new MyDocumentBuilder(), '')->getResult();
$this->fail($builder->result);
}
public function testSkipsBom()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseString($builder = new MyDocumentBuilder(), "\xef\xbb\xbf")->getResult();
$this->assertEquals("", $builder->result);
}
public function testAllowsTrickyQnames()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseString($builder = new MyDocumentBuilder(), "\xef\xbb\xbf<_.:_ xmlns:_.='tricky'/>")->getResult();
$this->assertEquals("<_.:_ xmlns:_.=\"tricky\">", $builder->result);
}
public function testRootNS()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$parser->parseString($builder = new MyDocumentBuilder(), "")->getResult();
$this->assertEquals('', $builder->result);
}
public function testAllowsXMLStylesheet()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$src = "";
$parser->parseString($builder = new MyDocumentBuilder(), $src)->getResult();
$this->assertEquals($src, $builder->result);
}
public function testFixOrRejectCDATAClose()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$src = ' ]]> ';
try
{
$parser->parseString($builder = new MyDocumentBuilder(), $src)->getResult();
$this->assertEquals(' ]]> ', $builder->result);
}
catch(PHPTAL_ParserException $e)
{ /* ok - rejecting is one way to do it */ }
}
/**
* @expectedException PHPTAL_ParserException
*/
public function testSelfClosingSyntaxError()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$src = '';
$parser->parseString($builder = new MyDocumentBuilder(), $src)->getResult();
}
public function testFixOrRejectEntities()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
$src = ' & ; Ā
&--;';
try
{
$parser->parseString($builder = new MyDocumentBuilder(), $src)->getResult();
$this->assertEquals(' & ; Ā
&--;', $builder->result);
}
catch(PHPTAL_ParserException $e)
{ /* ok - rejecting is one way to do it */ }
}
public function testLineAccuracy()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try
{
$parser->parseString(new PHPTAL_Dom_PHPTALDocumentBuilder(),
"1
3
4
error in line 6!
");
$this->fail("Accepted invalid XML");
}
catch(PHPTAL_ParserException $e)
{
$this->assertEquals(6, $e->srcLine);
}
}
public function testLineAccuracy2()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try
{
$parser->parseString(new PHPTAL_Dom_PHPTALDocumentBuilder(),
"
");
$this->fail("Accepted invalid XML");
}
catch(PHPTAL_ParserException $e)
{
$this->assertEquals(7, $e->srcLine);
}
}
public function testLineAccuracy3()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try
{
$parser->parseString(new PHPTAL_Dom_PHPTALDocumentBuilder(),
"
");
$this->fail("Accepted invalid XML");
}
catch(PHPTAL_ParserException $e)
{
$this->assertEquals(8, $e->srcLine);
}
}
public function testClosingRoot()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try
{
$parser->parseString(new PHPTAL_Dom_PHPTALDocumentBuilder(), "");
$this->fail("Accepted invalid XML");
}
catch(PHPTAL_ParserException $e)
{
$this->assertContains('ishallnotbeclosed', $e->getMessage());
$this->assertNotContains('imrootelement', $e->getMessage());
$this->assertNotContains("documentElement", $e->getMessage());
}
}
public function testNotClosing()
{
$parser = new PHPTAL_Dom_SaxXmlParser('UTF-8');
try
{
$parser->parseString(new PHPTAL_Dom_PHPTALDocumentBuilder(), "");
$this->fail("Accepted invalid XML");
}
catch(PHPTAL_ParserException $e)
{
$this->assertNotContains("documentElement", $e->getMessage());
$this->assertRegExp("/element_e.*element_d.*element_c.*element_b.*element_a/", $e->getMessage());
}
}
public function testSPRY()
{
$tpl = $this->newPHPTAL();
$tpl->setSource('
{someSpryRegion::element}
');
$tpl->prepare();
}
public function testSPRY2()
{
$tpl = $this->newPHPTAL();
$tpl->phptal_var = 'ok';
$tpl->setSource('
');
$this->assertXMLEquals('
', $tpl->execute());
}
}
class MyDocumentBuilder extends PHPTAL_Dom_DocumentBuilder
{
public $result;
public $elementStarts = 0;
public $elementCloses = 0;
public $specifics = 0;
public $datas = 0;
public $allow_xmldec = true;
public function __construct()
{
$this->result = '';
parent::__construct();
}
public function onDoctype($dt)
{
$this->specifics++;
$this->allow_xmldec = false;
$this->result .= $dt;
}
public function onXmlDecl($decl)
{
if (!$this->allow_xmldec) throw new Exception("more than one xml decl");
$this->specifics++;
$this->allow_xmldec = false;
$this->result .= $decl;
}
public function onCDATASection($data)
{
$this->onProcessingInstruction('');
}
public function onProcessingInstruction($data)
{
$this->specifics++;
$this->allow_xmldec = false;
$this->result .= $data;
}
public function onComment($data)
{
$this->onProcessingInstruction('');
}
public function onElementStart($name, array $attributes)
{
$this->allow_xmldec = false;
$this->elementStarts++;
$this->result .= "<$name";
$pairs = array();
foreach ($attributes as $key=>$value) $pairs[] = "$key=\"$value\"";
if (count($pairs) > 0) {
$this->result .= ' ' . join(' ', $pairs);
}
$this->result .= '>';
}
public function onElementClose($name)
{
$this->allow_xmldec = false;
$this->elementCloses++;
$this->result .= "$name>";
}
public function onElementData($data)
{
$this->datas++;
$this->result .= $data;
}
public function onDocumentStart(){}
public function onDocumentEnd(){}
public function getResult(){return $this->result;}
public function setEncoding($e) {}
}