求助:如何用DOMDocument打印完整XML并抓取URL链接生成XML?附报错
解决DOMDocument相关需求与致命错误问题
嘿,我来帮你一步步搞定这两个技术需求,顺便解决那个触发TypeError的致命错误问题~
一、先搞定DOMDocument::saveXML()的致命错误
你遇到的这个Fatal error原因很明确:DOMDocument::saveXML()方法接收的参数必须是DOMNode实例或者null,但你传了一个字符串。
举个错误的反例(就是你可能写的代码):
$dom = new DOMDocument(); // 错误:传字符串给saveXML() echo $dom->saveXML('<root><test>content</test></root>');
正确的用法是:
- 如果要输出整个XML文档,直接调用
$dom->saveXML()(不需要传参数) - 如果要输出某个特定节点,传入该节点的
DOMNode对象
比如正确示例:
$dom = new DOMDocument('1.0', 'UTF-8'); $dom->loadXML('<root><test>content</test></root>'); // 输出完整XML文档 echo htmlspecialchars($dom->saveXML()); // 或者输出根节点 echo htmlspecialchars($dom->saveXML($dom->documentElement));
二、实现你的两个技术需求
1. 使用DOMDocument打印完整的XML文档
这里分两种场景:加载已有XML字符串/文件,然后打印完整内容。
场景1:加载XML字符串并打印
// 初始化DOMDocument,设置版本和编码 $dom = new DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; // 开启格式化,让输出的XML更美观 // 加载XML字符串 $xmlContent = '<bookstore> <book category="fiction"> <title>Harry Potter</title> <author>J.K. Rowling</author> </book> </bookstore>'; $dom->loadXML($xmlContent); // 打印完整XML(用htmlspecialchars避免浏览器直接解析标签) echo htmlspecialchars($dom->saveXML());
场景2:加载XML文件并打印
$dom = new DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; // 加载本地XML文件 if ($dom->load('books.xml')) { echo htmlspecialchars($dom->saveXML()); } else { echo '加载XML文件失败'; }
2. 抓取指定URL的所有链接并以XML格式输出
这个需求需要先抓取网页内容,解析出所有<a>标签,再构建规范的XML输出。下面是完整可运行的代码:
// 目标URL $targetUrl = 'http://www.example.com/xxxx/'; // 步骤1:获取目标页面的HTML内容 $htmlContent = file_get_contents($targetUrl); if (!$htmlContent) { die('无法获取目标页面,请检查URL是否正确或网络连接'); } // 步骤2:解析HTML(网页HTML往往不规范,需要抑制解析错误) $dom = new DOMDocument(); libxml_use_internal_errors(true); // 关闭HTML解析错误提示 $dom->loadHTML($htmlContent); libxml_clear_errors(); // 清除解析过程中的错误记录 // 步骤3:用XPath提取所有<a>标签 $xpath = new DOMXPath($dom); $allLinks = $xpath->query('//a'); // 匹配所有<a>元素 // 步骤4:构建输出的XML文档 $outputXml = new DOMDocument('1.0', 'UTF-8'); $outputXml->formatOutput = true; // 创建根节点 $rootNode = $outputXml->createElement('extracted_links'); $outputXml->appendChild($rootNode); // 遍历所有链接,添加到XML中 foreach ($allLinks as $link) { // 获取链接的href属性 $href = $link->getAttribute('href'); // 处理相对链接,转换为绝对链接(避免输出相对路径) if (!parse_url($href, PHP_URL_SCHEME)) { $href = rtrim($targetUrl, '/') . '/' . ltrim($href, '/'); } // 获取链接文本,处理空文本的情况 $linkText = trim($link->nodeValue) ?: '无链接文本'; // 创建<a>元素并设置属性 $aElement = $outputXml->createElement('a'); $aElement->setAttribute('href', $href); $aElement->setAttribute('target', '_blank'); $aElement->nodeValue = $linkText; // 将<a>元素添加到根节点 $rootNode->appendChild($aElement); } // 步骤5:输出XML(设置正确的响应头) header('Content-Type: application/xml'); echo $outputXml->saveXML();
代码关键点说明:
- 处理相对链接:把页面中的相对路径(比如
/yyyy/)转换为绝对URL,确保输出的链接可直接访问 - 抑制HTML解析错误:网页HTML经常有不规范的标签,用
libxml_use_internal_errors(true)避免报错中断程序 - 规范XML构建:用DOMDocument的API创建节点和属性,避免手动拼接字符串导致的XML语法错误
内容的提问来源于stack exchange,提问作者Jazuly
相关产品推荐
相关产品推荐

