PHP Conference Japan 2024

DOMDocument 类

(PHP 5、PHP 7、PHP 8)

简介

表示整个 HTML 或 XML 文档;充当文档树的根。

类概要

class DOMDocument extends DOMNode implements DOMParentNode {
/* 继承的常量 */
/* 属性 */
public readonly ?DOMDocumentType $doctype;
public readonly ?DOMElement $documentElement;
public readonly ?string $actualEncoding;
public ?string $encoding;
public readonly ?string $xmlEncoding;
public ?string $version;
public readonly mixed $config;
public bool $recover;
public readonly ?DOMElement $firstElementChild;
public readonly ?DOMElement $lastElementChild;
public readonly int $childElementCount;
/* 继承的属性 */
public readonly string $nodeName;
public readonly int $nodeType;
public readonly ?DOMNode $parentNode;
public readonly ?DOMElement $parentElement;
public readonly DOMNodeList $childNodes;
public readonly ?DOMNode $firstChild;
public readonly ?DOMNode $lastChild;
public readonly ?DOMNode $previousSibling;
public readonly ?DOMNode $nextSibling;
public readonly ?DOMNamedNodeMap $attributes;
public readonly bool $isConnected;
public readonly ?DOMDocument $ownerDocument;
public readonly ?string $namespaceURI;
public string $prefix;
public readonly ?string $localName;
public readonly ?string $baseURI;
/* 方法 */
public __construct(string $version = "1.0", string $encoding = "")
public append(DOMNode|string ...$nodes): void
public createAttribute(string $localName): DOMAttr|false
public createAttributeNS(?string $namespace, string $qualifiedName): DOMAttr|false
public createElement(string $localName, string $value = ""): DOMElement|false
public createElementNS(?string $namespace, string $qualifiedName, string $value = ""): DOMElement|false
public getElementById(string $elementId): ?DOMElement
public getElementsByTagName(string $qualifiedName): DOMNodeList
public getElementsByTagNameNS(?string $namespace, string $localName): DOMNodeList
public importNode(DOMNode $node, bool $deep = false): DOMNode|false
public load(string $filename, int $options = 0): bool
public loadHTML(string $source, int $options = 0): bool
public loadHTMLFile(string $filename, int $options = 0): bool
public loadXML(string $source, int $options = 0): bool
public prepend(DOMNode|string ...$nodes): void
public registerNodeClass(string $baseClass, ?string $extendedClass): true
public relaxNGValidate(string $filename): bool

public save(字符串 $filename, 整数 $options = 0): 整数|false
public saveHTMLFile(字符串 $filename): 整数|false
public saveXML(?DOMNode $node = null, 整数 $options = 0): 字符串|false
public schemaValidate(字符串 $filename, 整数 $flags = 0): 布尔型
public schemaValidateSource(字符串 $source, 整数 $flags = 0): 布尔型
public xinclude(整数 $options = 0): 整数|false
/* 继承的方法 */
public DOMNode::C14N(
    布尔型 $exclusive = false,
    布尔型 $withComments = false,
    ?数组 $xpath = null,
    ?数组 $nsPrefixes = null
): 字符串|false
public DOMNode::C14NFile(
    字符串 $uri,
    布尔型 $exclusive = false,
    布尔型 $withComments = false,
    ?数组 $xpath = null,
    ?数组 $nsPrefixes = null
): 整数|false
}

属性

actualEncoding

自 PHP 8.4.0 起已弃用。文档的实际编码,是 encoding 的只读等价物。

childElementCount

子元素的数量。

config

自 PHP 8.4.0 起已弃用。调用 DOMDocument::normalizeDocument() 时使用的配置。

doctype

与该文档关联的文档类型声明。

documentElement

第一个文档元素的 DOMElement 对象。如果未找到,则评估结果为 null

documentURI

文档的位置或如果未定义则为 null

encoding

文档的编码,由 XML 声明指定。此属性在最终的 DOM Level 3 规范中不存在,但在此实现中是操作 XML 文档编码的唯一方法。

firstElementChild

第一个子元素或 null

formatOutput

使用缩进和额外空格美化输出格式。如果文档加载时启用了 preserveWhitespace,则此选项无效。

implementation

处理此文档的 DOMImplementation 对象。

lastElementChild

最后一个子元素或 null

preserveWhiteSpace

不要删除冗余的空白字符。默认为 true。将其设置为 false 与将 LIBXML_NOBLANKS 作为 option 传递给 DOMDocument::load() 等具有相同的效果。

recover

专有。启用恢复模式,即尝试解析非良构文档。此属性不是 DOM 规范的一部分,特定于 libxml。

resolveExternals

将其设置为 true 以从文档类型声明加载外部实体。这对于在 XML 文档中包含字符实体很有用。

standalone

已弃用。文档是否独立,由 XML 声明指定,对应于 xmlStandalone

strictErrorChecking

在错误时抛出 DOMException。默认为 true

substituteEntities

专有。是否替换实体。此属性不是 DOM 规范的一部分,特定于 libxml。默认为 false

注意

启用实体替换可能会助长 XML 外部实体 (XXE) 攻击。

validateOnParse

加载并根据 DTD 进行验证。默认为 false

注意

启用 DTD 验证可能会助长 XML 外部实体 (XXE) 攻击。

version

已弃用。XML 版本,对应于 xmlVersion

xmlEncoding

一个属性,作为 XML 声明的一部分,指定此文档的编码。当未指定或未知时,例如当文档在内存中创建时,此属性为 null

xmlStandalone

一个属性,作为 XML 声明的一部分,指定此文档是否独立。当未指定时,此属性为 false。独立文档是指没有外部标记声明的文档。此类标记声明的一个示例是 DTD 声明具有默认值的属性。

xmlVersion

一个属性,作为 XML 声明的一部分,指定此文档的版本号。如果没有声明并且此文档支持“XML”功能,则值为“1.0”。

变更日志

版本 描述
8.4.0 actualEncodingconfig 现在正式弃用。
8.0.0 DOMDocument 现在实现了 DOMParentNode
8.0.0 已删除未实现的方法 DOMDocument::renameNode()

备注

注意:

DOM 扩展使用 UTF-8 编码。使用 mb_convert_encoding()UConverter::transcode()iconv() 处理其他编码。

注意:

当在 DOMDocument 对象上使用 json_encode() 时,结果将是编码空对象的编码结果。

目录

添加注释

用户贡献的注释 19 个注释

Fernando H
16 年前
显示一个如何使用此类的快速示例,以便新用户可以快速入门,而无需自己弄清楚所有内容。(在发布之日,此文档刚刚添加,缺少示例。)

<?php

// 设置内容类型为 XML,以便浏览器将其识别为 XML。
header( "content-type: application/xml; charset=ISO-8859-15" );

// “创建”文档。
$xml = new DOMDocument( "1.0", "ISO-8859-15" );

// 创建一些元素。
$xml_album = $xml->createElement( "Album" );
$xml_track = $xml->createElement( "Track", "The ninth symphony" );

// 设置属性。
$xml_track->setAttribute( "length", "0:01:15" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );

// 创建另一个元素,仅用于演示您可以添加任意数量(对计算机来说是合理的)的子级。
$xml_note = $xml->createElement( "Note", "The last symphony composed by Ludwig van Beethoven." );

// 附加所有元素。
$xml_track->appendChild( $xml_note );
$xml_album->appendChild( $xml_track );

// 使用一些不同的值重复上述操作..
$xml_track = $xml->createElement( "Track", "Highway Blues" );

$xml_track->setAttribute( "length", "0:01:33" );
$xml_track->setAttribute( "bitrate", "64kb/s" );
$xml_track->setAttribute( "channels", "2" );
$xml_album->appendChild( $xml_track );

$xml->appendChild( $xml_album );

// 解析 XML。
print $xml->saveXML();

?>

输出
<Album>
<Track length="0:01:15" bitrate="64kb/s" channels="2">
The ninth symphony
<Note>
The last symphony composed by Ludwig van Beethoven.
</Note>
</Track>
<Track length="0:01:33" bitrate="64kb/s" channels="2">Highway Blues</Track>
</Album>

如果您希望您的 PHP->DOM 代码在 .xml 扩展名下运行,则应将 Web 服务器设置为使用 PHP 运行 .xml 扩展名(请参阅 PHP 的安装/配置配置以了解如何执行此操作)。

请注意,这
<?php
$xml
= new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = $xml->createElement( "Album" );
$xml_track = $xml->createElement( "Track" );
$xml_album->appendChild( $xml_track );
$xml->appendChild( $xml_album );
?>

与这
<?php
// 将无法工作。
$xml = new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = new DOMElement( "Album" );
$xml_track = new DOMElement( "Track" );
$xml_album->appendChild( $xml_track );
$xml->appendChild( $xml_album );
?>

不同,尽管这将起作用
<?php
$xml
= new DOMDocument( "1.0", "ISO-8859-15" );
$xml_album = new DOMElement( "Album" );
$xml->appendChild( $xml_album );
?>
developer at nabtron dot com
8 年前
对于来到这里并检查 utf-8 字符编码问题的用户来说,纠正它非常简单,无需在 html 中添加任何额外的输出标签。

我们将利用:mb_convert_encoding

感谢在之前的评论中分享 SmartDOMDocument 的用户,我得到了解决它的想法。但是我真的很希望他分享方法而不是提供链接。

无论如何,回到解决方案,您可以简单地使用

<?php

// 检查我们接收到的内容是否为空,以避免警告
if ( empty( $content ) ) {
return
false;
}

// 将所有特殊字符转换为 utf-8
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');

// 创建新文档
$doc = new DOMDocument('1.0', 'utf-8');

// 关闭一些错误
libxml_use_internal_errors(true);

// 它加载内容而不添加封闭的 html/body 标签以及 doctype 声明
$doc->LoadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

// 现在您可以对这段代码执行任何操作

?>

希望它能解决某些人的问题!如果您需要我的帮助或服务来修复您的代码,您可以通过 nabtron.com 联系我,或通过此评论中提到的电子邮件与我联系。
jay at jaygilford dot com
14 年前
这是我编写的一个小函数,用于使用 DOMDocument 获取所有页面链接,希望对其他人有所帮助

<?php
/**
* @author Jay Gilford
*/

/**
* get_links()
*
* @param string $url
* @return array
*/
function get_links($url) {

// 创建一个新的 DOM 文档来保存我们的网页结构
$xml = new DOMDocument();

// 将 url 的内容加载到 DOM 中
$xml->loadHTMLFile($url);

// 空数组,用于保存要返回的所有链接
$links = array();

// 循环遍历 dom 中的每个 <a> 标签并将其添加到链接数组中
foreach($xml->getElementsByTagName('a') as $link) {
$links[] = array('url' => $link->getAttribute('href'), 'text' => $link->nodeValue);
}

// 返回链接
return $links;
}
?>
andreas at userbrain dot com
3年前
在苦苦挣扎了几个小时,尝试解析和修改部分 HTML 内容后,我找到了这个解决方案,它对我很有效,并且与我在网上找到的其他方法相比,相对简单。

此解决方案修复了不需要的 DOCTYPE 以及 html、body 标签和编码问题。

<?php

// 假设内容使用 utf-8 编码
$content = "<h1>这是一个标题</h1><p>这是一个段落</p>";

// 将内容加载到一个 div 中,并使用 meta 标签指定编码
$temp_dom = new DOMDocument();
$temp_dom->loadHTML("<meta http-equiv='Content-Type' content='charset=utf-8' /><div>$content</div>");

// 由于 loadHTML() 也会添加 DOCTYPE 以及 <html> 和 <body> 标签,所以让我们创建一个新的 DOMDocument,并只导入我们需要的节点
$dom = new DOMDocument();
$first_div = $temp_dom->getElementsByTagName('div')[0];
$first_div_node = $dom->importNode($first_div, true);
$dom->appendChild($first_div_node);

// 做你想做的任何事情
$dom->getElementsByTagName('h1')[0]->setAttribute('class', 'happy');

// 如果你不介意 div 和空格,你也可以直接 echo $dom->saveHtml()
echo substr(trim($dom->saveHtml()), 5, -6);

// 输出:<h1 class="happy">这是一个标题</h1><p>这是一个段落</p>
?>
tloach at gmail dot com
14 年前
对于任何遇到 formatOuput 不起作用问题的其他人,这里有一个解决方法

与其只做类似这样的操作

<?php
$outXML
= $xml->saveXML();
?>

强制它从头加载 XML,然后它将正确格式化

<?php
$outXML
= $xml->saveXML();
$xml = new DOMDocument();
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
$xml->loadXML($outXML);
$outXML = $xml->saveXML();
?>
biker dot mike at gmx dot com
8 年前
在从字符串加载 XML 时,请注意以下陷阱

<?php
$doc
= new \DOMDocument;
$doc->documentURI = $myXmlFilename;
$doc->loadXML($myXmlString);
?>

documentURI 现在设置为 $myXmlFilename 的值,对吧?

错!

它被设置为当前工作目录。如果你想手动将 documentURI 设置为除 CWD 之外的其他值,请在调用 loadXML() 后执行。

例如
<?php
$doc
= new \DOMDocument;
$doc->loadXML($myXmlString);
$doc->documentURI = $myXmlFilename;
?>

documentURI 现在确实被设置为 $myXmlFilename 的值。
Nick M
13年前
你可能需要将 DOMDocument 的全部或部分内容保存为一个 XHTML 友好的字符串,使其兼容 XML 和 HTML 4。以下是用 saveXHTML 方法扩展的 DOMDocument 类

<?php

/**
* XHTML 文档
*
* 表示整个 XHTML DOM 文档;作为文档树的根。
*/
class XHTMLDocument extends DOMDocument {

/**
* 这些标签必须始终自结束。其他任何标签都不应自结束。
*
* @var array
*/
public $selfTerminate = array(
'area','base','basefont','br','col','frame','hr','img','input','link','meta','param'
);

/**
* saveXHTML
*
* 将内部 XML 树转储回 XHTML 友好的字符串。
*
* @param DOMNode $node
* 使用此参数输出特定节点而不是整个文档。
*/
public function saveXHTML(DOMNode $node=null) {

if (!
$node) $node = $this->firstChild;

$doc = new DOMDocument('1.0');
$clone = $doc->importNode($node->cloneNode(false), true);
$term = in_array(strtolower($clone->nodeName), $this->selfTerminate);
$inner='';

if (!
$term) {
$clone->appendChild(new DOMText(''));
if (
$node->childNodes) foreach ($node->childNodes as $child) {
$inner .= $this->saveXHTML($child);
}
}

$doc->appendChild($clone);
$out = $doc->saveXML($clone);

return
$term ? substr($out, 0, -2) . ' />' : str_replace('><', ">$inner<", $out);

}

}

?>

这个方法没有进行基准测试,但可能比 saveXML 或 saveHTML 慢得多,应该谨慎使用。
pastormontesinos at gmail dot com
3年前
在解析时安全地使用脚本节点的最佳选择是扩展 DOMDocument,在 DOMDocument 处理过程中保留脚本标签,并在调用 saveHTML 函数后重新排列它们。这是我的自定义类。



<?php

class SafeDOMDocument extends \DOMDocument
{
const
REGEX_JS = '#(\s*<!--(\[if[^\n]*>)?\s*(<script.*</script>)+\s*(<!\[endif\])?-->)|(\s*<script.*</script>)#isU';
const
SUBSTITUTION_FORMAT = '<!--<script class="script_%s"></script>-->';
private
$matchedScripts = [];

public function
loadHTML($source, $options = 0)
{
$this->formatOutput = false;
$this->preserveWhiteSpace = true;
$this->validateOnParse = false;
$this->strictErrorChecking = false;
$this->recover = false;
$this->resolveExternals = false;
$this->substituteEntities = false;
$matches = [];
$success = preg_match_all(self::REGEX_JS, $source, $matches);

if (
$success && !empty($matches)) {
foreach (
$matches[0] as $match) {
$storedScript = rtrim(ltrim($match, "\n\r\t "), "\n\r\t ");
$scriptId = md5($storedScript);
$key = sprintf(self::SUBSTITUTION_FORMAT, $scriptId);
$source = str_replace($match, $key, $source);
$this->matchedScripts[$key] = $storedScript;
}
}

return
parent::loadHTML($source, $options);
}

public function
saveHTML(DOMNode $node = null)
{
$output = parent::saveHTML($node);

if (
count($this->matchedScripts)) {
foreach (
$this->matchedScripts as $substitution => $originalSnippet) {
$output = str_replace($substitution, $originalSnippet, $output);
}
}

return
$output;
}
}
?>
[email protected]
14 年前
一个简洁实用的节点到数组转换函数,值得一试;)

<?php
function getArray($node)
{
$array = false;

if (
$node->hasAttributes())
{
foreach (
$node->attributes as $attr)
{
$array[$attr->nodeName] = $attr->nodeValue;
}
}

if (
$node->hasChildNodes())
{
if (
$node->childNodes->length == 1)
{
$array[$node->firstChild->nodeName] = $node->firstChild->nodeValue;
}
else
{
foreach (
$node->childNodes as $childNode)
{
if (
$childNode->nodeType != XML_TEXT_NODE)
{
$array[$childNode->nodeName][] = $this->getArray($childNode);
}
}
}
}

return
$array;
}
?>
fcartegnie
15年前
使用formatOutput()时要小心。

像这样创建空节点
createElement('foo','')
而不是
createElement('foo')
将会破坏formatOutput的功能。
[email protected]
2个月前
虽然DOMDocument理论上可以用来解析HTML,但它并不适合处理HTML文档,更适合处理格式良好的XML。使用DOMDocument处理HTML的主要问题之一是它对特殊字符(如&)的严格处理。

DOMDocument要求将&转义为&amp;,这符合XML标准,但在处理真实的HTML时可能不直观,因为在URL和文本中经常会发现原始的&字符。这种行为源于底层的基于XML的解析器(libxml),它以与XML相同的严格性对待HTML。

这个问题早在2001年就被报告过,但如今在使用DOMDocument处理HTML文档时,仍然会发生相同的解析错误。

开发人员常用的解决方法是抑制DOMDocument的错误报告,尤其是在解析错误(如未转义的&)发生时。但是,不建议抑制这些错误,尤其是在生产环境中,因为它可能会隐藏重要问题并带来潜在的安全风险。忽略或抑制错误可能会导致警告被忽略,如果没有得到妥善解决,可能会导致漏洞。

出于这些原因,建议主要将DOMDocument用于XML文档,或者在处理HTML时考虑使用更合适的库来避免这些问题。

theCoder / MV
[email protected]
15年前
此函数可以帮助调试当前的DOM元素



<?php
function dom_dump($obj) {
if (
$classname = get_class($obj)) {
$retval = "DOM节点列表实例: $classname,节点信息:\n";
switch (
true) {
case (
$obj instanceof DOMDocument):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->saveXML($obj);
break;
case (
$obj instanceof DOMElement):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->ownerDocument->saveXML($obj);
break;
case (
$obj instanceof DOMAttr):
$retval .= "XPath: {$obj->getNodePath()}\n".$obj->ownerDocument->saveXML($obj);
//$retval .= $obj->ownerDocument->saveXML($obj);
break;
case (
$obj instanceof DOMNodeList):
for (
$i = 0; $i < $obj->length; $i++) {
$retval .= "第 $i 项,XPath: {$obj->item($i)->getNodePath()}\n".
"{$obj->item($i)->ownerDocument->saveXML($obj->item($i))}\n";
}
break;
default:
return
"未知类实例";
}
} else {
return
'没有元素...';
}
return
htmlspecialchars($retval);
}
?>

示例用法

<?php
$dom
= new DomDocument();
$dom->load('test.xml');
$body = $dom->documentElement->getElementsByTagName('book');
echo
'<pre>'.dom_dump($body).'<pre>';
?>

输出

DOM节点列表实例,节点信息
第 0 项,XPath: /library/book[1]
<book isbn="0345342968">
<title>Fahrenheit 451</title>
<author>R. Bradbury</author>
<publisher>Del Rey</publisher>
</book>
第 1 项,XPath: /library/book[2]
<book isbn="0048231398">
<title>The Silmarillion</title>
<author>J.R.R. Tolkien</author>
<publisher>G. Allen &amp; Unwin</publisher>
</book>
第 2 项,XPath: /library/book[3]
<book isbn="0451524934">
<title>1984</title>
<author>G. Orwell</author>
<publisher>Signet</publisher>
</book>
第 3 项,XPath: /library/book[4]
<book isbn="031219126X">
<title>Frankenstein</title>
<author>M. Shelley</author>
<publisher>Bedford</publisher>
</book>
第 4 项,XPath: /library/book[5]
<book isbn="0312863551">
<title>The Moon Is a Harsh Mistress</title>
<author>R. A. Heinlein</author>
<publisher>Orb</publisher>
</book>
sites.sitesbr.net
11 年前
如何将具有以下层次结构的 DomDocument 对象化
<root>
<item>
<prop1>info1</prop1>
<prop2>info2</prop2>
<prop3>info3</prop3>
</item>
<item>
<prop1>info1</prop1>
<prop2>info2</prop2>
<prop3>info3</prop3>
</item>
</root>

是否可以使用对象风格来检索信息,例如

<?php
$theNodeValue
= $aitem->prop1;
?>

代码如下:一个类和两个函数。

<?php
ArrayNode{
public
$nodeName, $nodeValue;
}

function
getChildNodeElements( $domNode ){
$nodes = array();
for(
$i=0; $i < $domNode->childNodes->length; $i++){
$cn = $domNode->childNodes->item($i);
if(
$cn->nodeType == 1){
$nodes[] = $cn;
}
}
return
$nodes;
}

function
getArrayNodes( $domDoc ){
$res = array();

for(
$i=0; $i < $domDoc->childNodes->length; $i++){
$cn = $domDoc->childNodes->item($i);
# 第一个是根标签...
if( $cn->nodeType == 1){
# 但我们想要的是它的子节点。
$sub_cn = getChildNodeElements( $cn);
# 找到 tagName:
$baseItemTagName = $sub_cn[0]->nodeName;
break;
}
}

$dnl = $domDoc->getElementsByTagName( $baseItemTagName);

for(
$i=0; $i< $dnl->length; $i++){
$arrayNode = new ArrayNode();

# 摘要
$arrayNode->nodeName = $dnl->item($i)->nodeName;
$arrayNode->nodeValue = $dnl->item($i)->nodeValue;

# 子节点
$cn = $dnl->item($i)->childNodes;
for(
$k=0; $k<$cn->length; $k++){
if(
$cn->item($k)->nodeName == "#text" && trim($cn->item($k)->nodeValue) == "") continue;
$arrayNode->{$cn->item($k)->nodeName} = $cn->item($k)->nodeValue;
}

# 属性
$attr = $dnl->item($i)->attributes;
for(
$k=0; $k < $attr->length; $k++){
if(!
is_null($attr)){
if(
$attr->item($k)->nodeName == "#text" && trim($attr->item($k)->nodeValue) == "") continue;
$arrayNode->{$attr->item($k)->nodeName} = $attr->item($k)->nodeValue;
}
}

$res[] = $arrayNode;

}

return
$res;
}
?>

使用方法

<?php

# 首先,将 XML 加载到 DomDocument 变量中。

$url = "/path/to/yourxmlfile.xml";
$domSrc = file_get_contents($url);
$dom = new DomDocument();
$dom->loadXML( $domSrc );

# 然后,从 DomDocument 获取 ArrayNodes。

$ans = getArrayNodes( $dom );


for(
$i=0; $i < count( $ans ) ; $i++){

$cn = $ans[ $i];

$info1 = $cn->prop1;
$info2 = $cn->prop2;
$info3 = $cn->prop3;

// ...

}

?>
610010559 at qq dot com
2 年前
当您通过 appendChild() 方法向格式化的 XML 数据添加新元素时,您会发现添加的新元素未被格式化(即未被索引,也没有换行符)。以下是我提供的解决方案(简而言之,在不保留空白的情况下加载 XML),示例如下所示
<?php
$doc
= new \DOMDocument();
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;//这是关键,默认值为 true。
$doc->loadXML($xmlStr);
$doc->appendChild($doc->createElement('php', '666'))
$formattedXMLStr = $doc->saveXML();//DOMDocument 会为您格式化 xml 字符串
echo $formattedXMlStr;
?>
我尝试了很长时间才找到这个方法。希望它能节省您的时间。
ashjkshdu283 at gmail dot com
6 年前
/* 函数演变自 jay at jaygilford dot com 的帖子
* 此函数将返回指定
* 属性 ($attr) 在 Dom 文档对象的所有元素中的值的数组
*/

<?php

function getAttrData(string $attr, DomDocument $dom) {
// 用于存储所有要返回的类的空数组
$attrData = array();

// 循环遍历 DOM 中的每个标签,并将它的属性数据添加到数组中
foreach($dom->getElementsByTagName('*') as $tag) {
if(empty(
$tag->getAttribute($attr)) === false) {
array_push($attrData, $tag->getAttribute($attr));
}
}

// 返回属性数据数组
return array_unique($attrData);
}

$html = '
<!DOCTYPE html>
<html>
<head>
<title>页面标题</title>
</head>
<body>
<a href="#someLink" id="someLink" class="link-class">某个链接</a>
<a href="#someOtherLink" id="someOtherLink" class="link-class">另一个链接</a>
<h1 id="header1" class="header-class">我的第一个标题</h1>
<p id="para1" class="para-class">我的第一个段落。</p>
</body>
</html>'
;
$dom = new DOMDocument();
$dom->loadHtml($html);
$dom->saveHTML();
var_dump(getAttrData('class', $dom));
ingjetel at gmail dot com
9 年前
通过 DOM 解析轻松输出 XML 文件的基本函数

<?php
$dom
= new DomDocument();
$dom->load("./file.xml") or die("error");
$start = $dom->documentElement;
fc($start);

function
fc($node) {
$child = $node->childNodes;
foreach(
$child as $item) {
if (
$item->nodeType == XML_TEXT_NODE) {
if (
strlen(trim($item->nodeValue))) echo trim($item->nodeValue)."<br/>";
}
else if (
$item->nodeType == XML_ELEMENT_NODE) fc($item);
}
}
?>
danny dot nunez15 at gmail dot com
11 年前
一个简单的函数,用于获取页面中的所有链接。

function get_links($url) {

// 创建一个新的 DOM 文档来保存我们的网页结构
$xml = new DOMDocument();

// 将 url 的内容加载到 DOM 中

$xml->loadHTMLFile($url);

// 用于存储所有要返回的链接的空数组
$links = array();

// 循环遍历 DOM 中的每个 <a> 标签,并将其添加到链接数组中
foreach ($xml->getElementsByTagName('a') as $link) {
$url = $link->getAttribute('href');
if (!empty($url)) {
$links[] = $link->getAttribute('href');
}
}

// 返回链接
return $links;
}
admin at beerpla dot net
14 年前
在看到许多关于某些 DOMDocument 缺点的抱怨后,例如对编码的处理不当以及始终使用 <html>、<head> 和 DOCTYPE 保存 HTML 片段,我决定需要一个更好的解决方案。

所以,它来了:SmartDOMDocument。您可以在 http://beerpla.net/projects/smartdomdocument/ 找到它。

目前,主要亮点包括

- SmartDOMDocument 继承自 DOMDocument,因此非常易于使用 - 只需声明一个 SmartDOMDocument 类型的对象而不是 DOMDocument,并在所有现有功能之上享受新的行为(请参阅下面的示例)。

- saveHTMLExact() - DOMDocument 具有一个设计极其糟糕的“特性”,即如果您正在加载的 HTML 代码不包含 <html> 和 <body> 标签,它会自动添加它们(是的,没有标志可以关闭此行为)。
因此,当您调用 $doc->saveHTML() 时,您新保存的内容现在包含 <html><body> 和 DOCTYPE。在尝试处理代码片段时不太方便(XML 也有类似的问题)。
SmartDOMDocument 包含一个名为 saveHTMLExact() 的新函数,该函数可以完全满足您的需求 - 它可以保存 HTML,而无需添加 DOMDocument 添加的额外垃圾。

- 编码修复 - DOMDocument 众所周知没有正确处理编码(至少是 UTF-8),并且会使输出变得混乱。
SmartDOMDocument 试图通过增强 loadHTML() 来正确处理编码来解决此问题。此行为对您来说是透明的 - 只需像往常一样使用 loadHTML() 即可。

- SmartDOMDocument 对象作为字符串 - 您可以将 SmartDOMDocument 对象用作字符串,它将打印其内容。
例如
<?php
echo "HTML 内容如下: $smart_dom_doc";
?>

我将维护此代码并尝试修复出现的错误。

享受。
qrworld.net
10 年前
在这篇文章 http://softontherocks.blogspot.com/2014/11/descargar-el-contenido-de-una-url_11.html 中,我找到了一种使用 DOMDocument、loadHTMLFile 和 saveHTML() 获取 URL 内容的简单方法。

function getURLContent($url){
$doc = new DOMDocument;
$doc->preserveWhiteSpace = FALSE;
@$doc->loadHTMLFile($url);
return $doc->saveHTML();
}
To Top