PHP:用内置类DOMDocument解析XML/HTML文档

DOMDocument是PHP中用于处理XML和HTML文档的一个强大的内置类,它提供了一种基于文档对象模型(DOM)的方式来解析、操作和创建XML/HTML文档。以下是对DOMDocument的详细介绍:

一、创建DOMDocument对象及加载文档

创建对象:使用new DOMDocument()语句可以创建一个DOMDocument对象。

$dom = new DOMDocument();

加载XML/HTML文档:可以使用loadXML()方法加载一个包含XML内容的字符串,或者使用loadHTML()方法加载一个包含HTML内容的字符串。如果要从文件中加载文档,可以使用load()方法。

$dom = new DOMDocument();
// 从字符串加载XML
$xmlString = '<root><item>Value 1</item><item>Value 2</item></root>';
$dom->loadXML($xmlString);
// 从字符串加载HTML
$htmlString = '<div><p>Paragraph 1</p><p>Paragraph 2</p></div>';
$dom->loadHTML($htmlString);
// 从文件加载XML/HTML
$filePath = 'document.xml';
$dom->load($filePath);
// 从网址中加载HTML
$url = 'https://example.com';
$dom->loadHTML(file_get_contents($url));

二、使用 DOMDocument 解析 HTML 文档中特定元素

1. 通过标签名获取特定元素

使用 getElementsByTagName 方法可以获取具有指定标签名的所有元素。例如,要获取所有的 <p> 标签:

$dom = new DOMDocument();
$url = 'https://example.com';
$dom->loadHTML(file_get_contents($url));
$paragraphs = $dom->getElementsByTagName('p');
foreach ($paragraphs as $paragraph) {
    echo $paragraph->nodeValue. "\n";
}

2. 通过 ID 获取特定元素

如果元素具有 id 属性,可以使用 getElementById 方法直接获取该元素。例如,获取 id 为 myDiv 的 <div> 元素:

$myDiv = $dom->getElementById('myDiv');
if ($myDiv) {
    echo $myDiv->nodeValue. "\n";
}

3. 获取具有特定类名的元素

要获取具有特定类名的元素,需要先获取所有的元素,然后遍历这些元素,判断它们的 class 属性是否包含指定的类名。以下是一个示例,用于获取所有具有 myClass 类名的 <div> 元素:

$divs = $dom->getElementsByTagName('div');
foreach ($divs as $div) {
    $classAttribute = $div->getAttribute('class');
    if ($classAttribute && strpos($classAttribute,'myClass')!== false) {
        echo $div->nodeValue. "\n";
    }
}

4. 获取元素内的特定子元素

如果要获取某个元素内的特定子元素,可以先获取父元素,然后再在父元素内查找子元素。例如,获取 id 为 myDiv 的 <div> 元素内的所有 <a> 标签:

$myDiv = $dom->getElementById('myDiv');
if ($myDiv) {
    $links = $myDiv->getElementsByTagName('a');
    foreach ($links as $link) {
        echo $link->getAttribute('href'). "\n";
    }
}

5. 获取元素的属性值

使用 getAttribute 方法可以获取元素的指定属性值。例如,获取 <a> 标签的 href 属性值:

$links = $dom->getElementsByTagName('a');
foreach ($links as $link) {
    echo $link->getAttribute('href'). "\n";
}

6. 修改元素的属性值或内容

修改属性值:使用 setAttribute 方法可以修改元素的属性值。例如,将 <a> 标签的 href 属性值修改为新的链接:

$links = $dom->getElementsByTagName('a');
foreach ($links as $link) {
    $link->setAttribute('href', 'https://newexample.com');
    echo $link->getAttribute('href'). "\n";
}

修改元素内容:通过修改元素节点的 nodeValue 属性来改变元素的文本内容。例如,修改 <p> 标签内的文本:

$paragraphs = $dom->getElementsByTagName('p');
foreach ($paragraphs as $paragraph) {
    $paragraph->nodeValue = '这是修改后的段落。';
    echo $paragraph->nodeValue. "\n";
}

通过以上方法,可以灵活地使用 DOMDocument 类来解析 HTML 文档中的各种特定元素,并对其进行相应的操作。

获取和设置元素属性:使用getAttribute()方法可以获取元素的属性值,使用setAttribute()方法可以设置元素的属性。

$html = '<a href="https://example.com">Link</a><img src="image.jpg">';
$dom->loadHTML($html);
$link = $dom->getElementsByTagName('a')[0];
echo $link->getAttribute('href'). "\n"; 
$img = $dom->getElementsByTagName('img')[0];
$img->setAttribute('src', 'new_image.jpg');
echo $img->getAttribute('src'). "\n";

修改元素内容:可以通过修改元素节点的nodeValue属性来改变元素的文本内容,或者使用innerHTML属性来修改元素的HTML内容。

$html = '<div><p>Old Text</p></div>';
$dom->loadHTML($html);
$p = $dom->getElementsByTagName('p')[0];
echo $p->nodeValue. "\n"; 
$p->nodeValue = 'New Text';
echo $p->nodeValue. "\n"; 
// 修改HTML内容需要引入一些额外的处理,以下是一种简单示例
$div = $dom->getElementsByTagName('div')[0];
$newHtml = '<p><b>New HTML</b></p>';
$fragment = $dom->createDocumentFragment();
$fragment->appendXML($newHtml);
$div->replaceChild($fragment, $div->firstChild);
echo $dom->saveHTML($div);

三、创建和添加新元素

使用createElement()方法可以创建新的元素节点,然后使用appendChild()方法将其添加到文档中的指定位置。

$html = '<div><p>Paragraph</p></div>';
$dom->loadHTML($html);
$newParagraph = $dom->createElement('p');
$newParagraph->nodeValue = 'New Paragraph';
$div = $dom->getElementsByTagName('div')[0];
$div->appendChild($newParagraph);
echo $dom->saveHTML();

四、删除元素

使用removeChild()方法可以从文档中删除指定的元素节点。

$html = '<div><p>Paragraph 1</p><p>Paragraph 2</p></div>';
$dom->loadHTML($html);
$div = $dom->getElementsByTagName('div')[0];
$paragraphToRemove = $div->getElementsByTagName('p')[0];
$div->removeChild($paragraphToRemove);
echo $dom->saveHTML();

五、保存文档

使用saveXML()方法可以将DOMDocument对象表示的XML文档保存为字符串形式,使用saveHTML()方法可以将其保存为HTML格式的字符串。如果要将文档保存到文件中,可以结合file_put_contents()等函数来实现。

$dom = new DOMDocument();
$dom->loadXML('<root><item>Value</item></root>');
$xmlString = $dom->saveXML();
echo $xmlString;
$htmlString = $dom->saveHTML();
echo $htmlString;
// 保存到文件
file_put_contents('output.xml', $dom->saveXML());
file_put_contents('output.html', $dom->saveHTML());

六、优缺点

优点:

功能强大且全面,能够处理各种复杂的XML和HTML文档结构,提供了丰富的方法和属性来精确地操作文档中的元素、属性和内容。

基于标准的DOM模型,与其他遵循DOM规范的语言和工具具有较好的兼容性和互操作性,便于在不同的环境中进行数据交换和处理。

对XML和HTML的解析和处理更加严格和准确,能够更好地处理文档的合法性和完整性,避免一些因不规范文档导致的潜在问题。

缺点:

相对来说,使用DOMDocument类编写的代码较为冗长和复杂,需要对DOM模型和相关方法有较深入的理解,学习曲线相对较陡。

对于大规模的文档处理,由于其需要将整个文档加载到内存中并构建DOM树,可能会占用较多的内存资源,导致性能问题,尤其是在处理非常大的XML或HTML文件时。

DOMDocument类是PHP中处理XML和HTML文档的重要工具,虽然使用起来相对复杂一些,但在处理复杂文档结构和需要精确控制文档内容的场景中具有不可替代的优势。

PHP编程语言基础