XMLSerializer.php 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. <?php declare(strict_types = 1);
  2. namespace TheSeer\Tokenizer;
  3. use DOMDocument;
  4. class XMLSerializer {
  5. /**
  6. * @var \XMLWriter
  7. */
  8. private $writer;
  9. /**
  10. * @var Token
  11. */
  12. private $previousToken;
  13. /**
  14. * @var NamespaceUri
  15. */
  16. private $xmlns;
  17. /**
  18. * XMLSerializer constructor.
  19. *
  20. * @param NamespaceUri $xmlns
  21. */
  22. public function __construct(NamespaceUri $xmlns = null) {
  23. if ($xmlns === null) {
  24. $xmlns = new NamespaceUri('https://github.com/theseer/tokenizer');
  25. }
  26. $this->xmlns = $xmlns;
  27. }
  28. /**
  29. * @param TokenCollection $tokens
  30. *
  31. * @return DOMDocument
  32. */
  33. public function toDom(TokenCollection $tokens): DOMDocument {
  34. $dom = new DOMDocument();
  35. $dom->preserveWhiteSpace = false;
  36. $dom->loadXML($this->toXML($tokens));
  37. return $dom;
  38. }
  39. /**
  40. * @param TokenCollection $tokens
  41. *
  42. * @return string
  43. */
  44. public function toXML(TokenCollection $tokens): string {
  45. $this->writer = new \XMLWriter();
  46. $this->writer->openMemory();
  47. $this->writer->setIndent(true);
  48. $this->writer->startDocument();
  49. $this->writer->startElement('source');
  50. $this->writer->writeAttribute('xmlns', $this->xmlns->asString());
  51. $this->writer->startElement('line');
  52. $this->writer->writeAttribute('no', '1');
  53. $this->previousToken = $tokens[0];
  54. foreach ($tokens as $token) {
  55. $this->addToken($token);
  56. }
  57. $this->writer->endElement();
  58. $this->writer->endElement();
  59. $this->writer->endDocument();
  60. return $this->writer->outputMemory();
  61. }
  62. /**
  63. * @param Token $token
  64. */
  65. private function addToken(Token $token) {
  66. if ($this->previousToken->getLine() < $token->getLine()) {
  67. $this->writer->endElement();
  68. $this->writer->startElement('line');
  69. $this->writer->writeAttribute('no', (string)$token->getLine());
  70. $this->previousToken = $token;
  71. }
  72. if ($token->getValue() !== '') {
  73. $this->writer->startElement('token');
  74. $this->writer->writeAttribute('name', $token->getName());
  75. $this->writer->writeRaw(htmlspecialchars($token->getValue(), ENT_NOQUOTES | ENT_DISALLOWED | ENT_XML1));
  76. $this->writer->endElement();
  77. }
  78. }
  79. }