PHP实现XML转HTML并保留强调格式的技术问题
解决SimpleXML解析DocBook XML丢失强调内容并转为HTML的问题
问题分析
你当前的代码存在两个核心问题:
- 错误使用
$xml_data['para']访问元素——这是XML属性的调用语法,而<para>是<article>的子元素,正确写法应为$xml_data->para。 - SimpleXML直接输出元素时仅提取纯文本节点,会忽略
<emphasis>这类子元素,导致强调内容丢失,也无法完成DocBook标签到HTML标签的转换。
解决方案
推荐使用DOMDocument配合XPath处理,它能精准遍历混合内容(文本+子元素),完美完成标签转换:
$filedata = '<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE article> <article xmlns="http://docbook.org/ns/docbook" version="5.0" xmlns:xlink="http://www.w3.org/1999/xlink" > <para> This is an <emphasis role="strong">test</emphasis> sentence. </para> </article>'; // 初始化DOM和XPath $dom = new DOMDocument(); $dom->loadXML($filedata); $xpath = new DOMXPath($dom); // 注册DocBook命名空间(匹配XML中的xmlns属性) $xpath->registerNamespace('db', 'http://docbook.org/ns/docbook'); // 定位所有para元素 $paraNodes = $xpath->query('//db:para'); foreach ($paraNodes as $paraNode) { $htmlOutput = ''; // 遍历para下的所有子节点 foreach ($paraNode->childNodes as $node) { if ($node instanceof DOMText) { // 处理文本节点,转义特殊字符避免XSS $htmlOutput .= htmlspecialchars(trim($node->nodeValue)); } elseif ($node instanceof DOMElement && $node->tagName === 'emphasis') { // 根据role属性转换为对应HTML标签 if ($node->getAttribute('role') === 'strong') { $htmlOutput .= '<b>' . $node->nodeValue . '</b>'; } else { // 非strong的emphasis默认转为em标签,可按需调整 $htmlOutput .= '<em>' . $node->nodeValue . '</em>'; } } } echo trim($htmlOutput); }
代码说明
- 命名空间注册:DocBook XML带有
xmlns属性,必须通过XPath注册才能正确定位元素。 - 节点类型区分:分别处理文本节点和元素节点,文本节点做HTML转义,元素节点根据属性转换为对应HTML标签。
- 混合内容处理:DOM可以完整保留文本与子元素的结构,不会丢失任何内容。
替代方案(SimpleXML)
如果坚持使用SimpleXML,需手动遍历子元素并拼接内容,但处理混合内容的直观性不如DOM:
$xml_data = simplexml_load_string($filedata); $para = $xml_data->para; $output = ''; // 处理para开头的文本 $output .= trim((string)$para); // 遍历para下的子元素 foreach ($para->children() as $child) { if ($child->getName() === 'emphasis' && (string)$child['role'] === 'strong') { $output .= '<b>' . (string)$child . '</b>'; } // 处理子元素后的文本 $output .= $child->nextSibling; } echo trim($output);
内容的提问来源于stack exchange,提问作者Christophe Gratessolle
相关产品推荐
相关产品推荐

