[DOC-CVS] [phd] master: Support MathML (mml:*) elements for XHTML rendering (#236)

[email protected] (Louis-Arnaud via GitHub)
Newsgroups php.doc.cvs
Message-ID <[email protected]>
Author: Louis-Arnaud (lacatoire)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2026-02-05T17:04:33Z

Commit: https://github.com/php/phd/commit/61ad3e7cb0631a16ca603837c2213951f62d11ec
Raw diff: https://github.com/php/phd/commit/61ad3e7cb0631a16ca603837c2213951f62d11ec.diff

Support MathML (mml:*) elements for XHTML rendering (#236)

Closes #172

Changed paths:
  A  tests/package/php/data/mathml_rendering.xml
  A  tests/package/php/mathml_rendering.phpt
  M  phpdotnet/phd/Package/Generic/XHTML.php
  M  phpdotnet/phd/Reader.php


Diff:

diff --git a/phpdotnet/phd/Package/Generic/XHTML.php b/phpdotnet/phd/Package/Generic/XHTML.php
index 156c5d03..52433334 100644
--- a/phpdotnet/phd/Package/Generic/XHTML.php
+++ b/phpdotnet/phd/Package/Generic/XHTML.php
@@ -392,6 +392,48 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
         //phd
         'phd:toc'               => 'format_phd_toc',
 
+        // MathML (namespace http://www.w3.org/1998/Math/MathML)
+        'mml:math'              => 'format_mml_element',
+        // Token
+        'mml:mi'                => 'format_mml_element',
+        'mml:mn'                => 'format_mml_element',
+        'mml:mo'                => 'format_mml_element',
+        'mml:mtext'             => 'format_mml_element',
+        'mml:mspace'            => 'format_mml_element',
+        'mml:ms'                => 'format_mml_element',
+        // Layout
+        'mml:mrow'              => 'format_mml_element',
+        'mml:mfrac'             => 'format_mml_element',
+        'mml:msqrt'             => 'format_mml_element',
+        'mml:mroot'             => 'format_mml_element',
+        'mml:mstyle'            => 'format_mml_element',
+        'mml:merror'            => 'format_mml_element',
+        'mml:mpadded'           => 'format_mml_element',
+        'mml:mphantom'          => 'format_mml_element',
+        'mml:mfenced'           => 'format_mml_element',
+        'mml:menclose'          => 'format_mml_element',
+        // Scripts and limits
+        'mml:msub'              => 'format_mml_element',
+        'mml:msup'              => 'format_mml_element',
+        'mml:msubsup'           => 'format_mml_element',
+        'mml:munder'            => 'format_mml_element',
+        'mml:mover'             => 'format_mml_element',
+        'mml:munderover'        => 'format_mml_element',
+        'mml:mmultiscripts'     => 'format_mml_element',
+        'mml:mprescripts'       => 'format_mml_element',
+        'mml:none'              => 'format_mml_element',
+        // Tables
+        'mml:mtable'            => 'format_mml_element',
+        'mml:mtr'               => 'format_mml_element',
+        'mml:mtd'               => 'format_mml_element',
+        'mml:mlabeledtr'        => 'format_mml_element',
+        // Semantics
+        'mml:semantics'         => 'format_mml_element',
+        'mml:annotation'        => 'format_mml_element',
+        'mml:annotation-xml'    => 'format_mml_element',
+        // Actions
+        'mml:maction'           => 'format_mml_element',
+
     ); /* }}} */
 
     private $mytextmap = array(
@@ -631,6 +673,37 @@ function format_phd_toc($open, $name, $attrs, $props) {
         ) . "</div>\n";
     }
 
+    /**
+    * Handle MathML elements (mml:* namespace).
+    * Strips the "mml:" prefix and outputs the HTML5 local name.
+    */
+    public function format_mml_element($open, $name, $attrs, $props) {
+        $localName = substr($name, 4);
+
+        if ($open) {
+            $attrStr = '';
+
+            // Add xmlns on the <math> root element for XHTML compatibility
+            if ($localName === 'math') {
+                $attrStr .= ' xmlns="' . Reader::XMLNS_MATHML . '"';
+            }
+
+            // Preserve MathML attributes (stored under XMLNS_DOCBOOK as they have no namespace)
+            foreach ($attrs[Reader::XMLNS_DOCBOOK] as $attr => $val) {
+                $attrStr .= ' ' . $attr . '="' . $this->TEXT($val) . '"';
+            }
+
+            // Preserve xml:id as id
+            if (isset($attrs[Reader::XMLNS_XML]["id"])) {
+                $attrStr .= ' id="' . $attrs[Reader::XMLNS_XML]["id"] . '"';
+            }
+
+            return '<' . $localName . $attrStr . ($props["empty"] ? '/>' : '>');
+        }
+
+        return '</' . $localName . '>';
+    }
+
     public function createLink($for, &$desc = null, $type = Format::SDESC) {
         $retval = null;
         if (isset($this->indexes[$for])) {
diff --git a/phpdotnet/phd/Reader.php b/phpdotnet/phd/Reader.php
index 796a2d71..47240f14 100644
--- a/phpdotnet/phd/Reader.php
+++ b/phpdotnet/phd/Reader.php
@@ -7,6 +7,7 @@ class Reader extends \XMLReader
     const XMLNS_XLINK   = "http://www.w3.org/1999/xlink";
     const XMLNS_PHD     = "http://www.php.net/ns/phd";
     const XMLNS_DOCBOOK = "http://docbook.org/ns/docbook";
+    const XMLNS_MATHML  = "http://www.w3.org/1998/Math/MathML";
     
     protected OutputHandler $outputHandler;
 
diff --git a/tests/package/php/data/mathml_rendering.xml b/tests/package/php/data/mathml_rendering.xml
new file mode 100644
index 00000000..c32c7dfe
--- /dev/null
+++ b/tests/package/php/data/mathml_rendering.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter xml:id="mathml_rendering" xmlns="http://docbook.org/ns/docbook" xmlns:mml="http://www.w3.org/1998/Math/MathML">
+
+ <section>
+  <para>1. Inline MathML equation</para>
+  <para>
+   The quadratic formula is
+   <mml:math display="inline"><mml:mi>x</mml:mi><mml:mo>=</mml:mo><mml:mfrac><mml:mrow><mml:mo>-</mml:mo><mml:mi>b</mml:mi><mml:mo>±</mml:mo><mml:msqrt><mml:mrow><mml:msup><mml:mi>b</mml:mi><mml:mn>2</mml:mn></mml:msup><mml:mo>-</mml:mo><mml:mn>4</mml:mn><mml:mi>a</mml:mi><mml:mi>c</mml:mi></mml:mrow></mml:msqrt></mml:mrow><mml:mrow><mml:mn>2</mml:mn><mml:mi>a</mml:mi></mml:mrow></mml:mfrac></mml:math>.
+  </para>
+ </section>
+
+ <section>
+  <para>2. Self-closing mspace element</para>
+  <para>
+   <mml:math><mml:mi>a</mml:mi><mml:mspace width="1em"/><mml:mi>b</mml:mi></mml:math>
+  </para>
+ </section>
+
+ <section>
+  <para>3. Element with mathvariant attribute</para>
+  <para>
+   <mml:math><mml:mi mathvariant="bold">x</mml:mi></mml:math>
+  </para>
+ </section>
+
+</chapter>
diff --git a/tests/package/php/mathml_rendering.phpt b/tests/package/php/mathml_rendering.phpt
new file mode 100644
index 00000000..f755da39
--- /dev/null
+++ b/tests/package/php/mathml_rendering.phpt
@@ -0,0 +1,46 @@
+--TEST--
+MathML rendering
+--FILE--
+<?php
+namespace phpdotnet\phd;
+
+require_once __DIR__ . "/../../setup.php";
+
+$xmlFile = __DIR__ . "/data/mathml_rendering.xml";
+
+$config->xmlFile = $xmlFile;
+
+$format = new TestPHPChunkedXHTML($config, $outputHandler);
+
+$render = new TestRender(new Reader($outputHandler), $config, $format);
+
+$render->run();
+?>
+--EXPECT--
+Filename: mathml_rendering.html
+Content:
+<div id="mathml_rendering" class="chapter">
+
+ <div class="section">
+  <p class="para">1. Inline MathML equation</p>
+  <p class="para">
+   The quadratic formula is
+   <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mi>x</mi><mo>=</mo><mfrac><mrow><mo>-</mo><mi>b</mi><mo>±</mo><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mo>-</mo><mn>4</mn><mi>a</mi><mi>c</mi></mrow></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></math>.
+  </p>
+ </div>
+
+ <div class="section">
+  <p class="para">2. Self-closing mspace element</p>
+  <p class="para">
+   <math xmlns="http://www.w3.org/1998/Math/MathML"><mi>a</mi><mspace width="1em"/><mi>b</mi></math>
+  </p>
+ </div>
+
+ <div class="section">
+  <p class="para">3. Element with mathvariant attribute</p>
+  <p class="para">
+   <math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="bold">x</mi></math>
+  </p>
+ </div>
+
+</div>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.