如何用PHP解析特定MathML节点前的同级子节点并转为数组
解决MathML按
<mspace linebreak="newline"/>分组解析为数组的问题 你当前的代码混用了SimpleXML和DOM,而且逻辑上只是把每个单独的子节点(比如<mn>、<mi>)分别存入数组,没有实现按<mspace>分组的需求。我们可以用纯DOM结合XPath来处理,逻辑更清晰准确:
<?php // 读取XML文件内容(也可以直接传入字符串) $xmlContent = file_get_contents('answer.xml'); $dom = new DOMDocument(); $dom->loadXML($xmlContent); $xpath = new DOMXPath($dom); // 注册MathML命名空间,适配XML里的xmlns属性 $xpath->registerNamespace('mathml', 'http://www.w3.org/1998/Math/MathML'); $result = []; $currentGroup = []; // 获取<math>根节点下的所有直接子节点 $mathChildren = $xpath->query('/mathml:math/node()'); foreach ($mathChildren as $node) { // 跳过空白文本节点(XML里的空格会被解析成无意义的文本节点) if ($node instanceof DOMText && trim($node->nodeValue) === '') { continue; } // 遇到目标换行节点时,将当前组拼接为XML字符串存入结果 if ($node->tagName === 'mspace' && $node->getAttribute('linebreak') === 'newline') { if (!empty($currentGroup)) { $groupXml = ''; foreach ($currentGroup as $childNode) { $groupXml .= $dom->saveXML($childNode); } $result[] = $groupXml; $currentGroup = []; } } else { // 非换行节点则加入当前分组 $currentGroup[] = $node; } } // 处理最后一组(最后没有换行节点的情况) if (!empty($currentGroup)) { $groupXml = ''; foreach ($currentGroup as $childNode) { $groupXml .= $dom->saveXML($childNode); } $result[] = $groupXml; } // 输出最终结果 print_r($result); ?>
代码关键说明:
- 命名空间注册:因为你的MathML带有
xmlns属性,必须通过XPath注册命名空间才能正确定位节点; - 空白节点过滤:XML中的空格会被解析为DOMText节点,需要跳过这些无意义节点避免干扰分组;
- 分组逻辑:遍历节点时收集非换行节点,遇到目标
<mspace>就将当前收集的节点拼接为XML字符串存入数组,最后单独处理末尾未被换行节点分隔的内容。
运行后你会得到符合预期的结果:
Array ( [0] => <mn>2</mn><mi>x</mi><mo>+</mo><mn>2</mn><mo>=</mo><mn>3</mn> [1] => <mn>2</mn><mi>x</mi><mo>=</mo><mn>3</mn><mo>-</mo><mn>2</mn> [2] => <mn>2</mn><mi>x</mi><mo>=</mo><mn>1</mn> [3] => <mi>x</mi><mo>=</mo><mfrac><mn>1</mn><mn>2</mn></mfrac> )
内容的提问来源于stack exchange,提问作者jai wilshere
相关产品推荐
相关产品推荐

