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): bool
public relaxNGValidate(string $filename): bool
public replaceChildren(DOMNode|string ...$nodes): void
public save(string $filename, int $options = 0): int|false
public saveHTML(?DOMNode $node = null): string|false
public saveHTMLFile(string $filename): int|false
public saveXML(?DOMNode $node = null, int $options = 0): string|false
public schemaValidate(string $filename, int $flags = 0): bool
public schemaValidateSource(string $source, int $flags = 0): bool
public validate(): bool
public xinclude(int $options = 0): int|false
/* 继承的方法 */
public DOMNode::C14N(
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): string|false
public DOMNode::C14NFile(
    string $uri,
    bool $exclusive = false,
    bool $withComments = false,
    ?array $xpath = null,
    ?array $nsPrefixes = null
): int|false
public DOMNode::isEqualNode(?DOMNode $otherNode): bool
public DOMNode::isSameNode(DOMNode $otherNode): bool
public DOMNode::isSupported(string $feature, string $version): bool
}

属性

actualEncoding

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

childElementCount

子元素的数量。

config

已弃用。当调用 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.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 );
?>
andreas at userbrain dot com
2 年前
在与解析和修改部分 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');

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

// 输出:<h1 class="happy">这是一个标题</h1><p>这是一个段落</p>
?>
nabtron.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 上联系我,或通过此评论中提到的电子邮件联系我。
[email protected]
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;
}
?>
[email protected]
14 年前
对于其他遇到 formatOutput 不起作用问题的人,这里有一个解决方法

而不是只做类似以下的事情

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

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

<?php
$outXML
= $xml->saveXML();
$xml = new DOMDocument();
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
$xml->loadXML($outXML);
$outXML = $xml->saveXML();
?>
[email protected]
13 年前
我写了一个不错且简单的节点到数组的函数,值得一试;)

<?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;
}
?>
[email protected]
7 年前
从字符串加载 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 慢得多,应谨慎使用。
fcartegnie
14 年前
小心使用 formatOutput()。

像这样创建一个空节点
createElement('foo','')
而不是
createElement('foo')
将破坏 formatOutput。
cmyk777 at gmail dot com
15 年前
此函数可能有助于调试当前的 dom 元素。

<?php
function dom_dump($obj) {
if (
$classname = get_class($obj)) {
$retval = "Instance of $classname, node list: \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 .= "Item #$i, XPath: {$obj->item($i)->getNodePath()}\n".
"{$obj->item($i)->ownerDocument->saveXML($obj->item($i))}\n";
}
break;
default:
return
"Instance of unknown class";
}
} else {
return
'no elements...';
}
return
htmlspecialchars($retval);
}
?>

示例用法

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

输出

Instance of DOMNodeList, node list
Item #0, XPath: /library/book[1]
<book isbn="0345342968">
<title>Fahrenheit 451</title>
<author>R. Bradbury</author>
<publisher>Del Rey</publisher>
</book>
Item #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>
Item #2, XPath: /library/book[3]
<book isbn="0451524934">
<title>1984</title>
<author>G. Orwell</author>
<publisher>Signet</publisher>
</book>
Item #3, XPath: /library/book[4]
<book isbn="031219126X">
<title>Frankenstein</title>
<author>M. Shelley</author>
<publisher>Bedford</publisher>
</book>
Item #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>
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;
?>
我尝试了很长时间,希望可以节省您的时间。
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;
?>

以下是代码:一个类和 2 个函数。

<?php
class 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);
# The first is the root tag...
if( $cn->nodeType == 1){
# But we want it's childNodes.
$sub_cn = getChildNodeElements( $cn);
# Found the tagName:
$baseItemTagName = $sub_cn[0]->nodeName;
break;
}
}

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

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

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

# Child Nodes
$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;
}

# Attributes
$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;
}
?>

To use it

<?php

# First you load a XML in a DomDocument variable.

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

# Then, you get the ArrayNodes from the DomDocument.

$ans = getArrayNodes( $dom );


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

$cn = $ans[ $i];

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

// ...

}

?>
pastormontesinos at gmail dot com
3 years ago
在解析时,为了安全使用脚本节点,最好的选择是扩展 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;
}
}
?>
ashjkshdu283 at gmail dot com
6 年前
/* 该函数演变自 jay at jaygilford dot com 的帖子
* 此函数将返回 Dom 文档对象中所有元素的指定
* 属性($attr)值的数组
*/

<?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>Page Title</title>
</head>
<body>
<a href="#someLink" id="someLink" class="link-class">Some Link</a>
<a href="#someOtherLink" id="someOtherLink" class="link-class">Some Other Link</a>
<h1 id="header1" class="header-class">My First Heading</h1>
<p id="para1" class="para-class">My first paragraph.</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);
}
}
?>
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 "Here is the HTML: $smart_dom_doc";
?>

我将维护此代码,并尝试在出现错误时修复它们。

尽情享受。
danny dot nunez15 at gmail dot com
10 年前
一个简单的函数来获取页面中的所有链接。

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;
}
PhilipWayneRollins at gmail dot com
14 年前
如果您想使用 DOMDocument 创建 xHTML 文档,这里有一个简单的类

请注意,这是为了从头开始创建 xHTML 文档,但可以轻松扩展以使用 xHTML 文档。这也适用于 xHTML,而不是 XML。

<?php
class Document
{
public
$doctype;
public
$head;
public
$title = 'Sensei Ninja';
public
$body;
private
$styles;
private
$metas;
private
$scripts;
private
$document;


function
__construct ( )
{
$this->document = new DOMDocument( );
$this->head = $this->document->createElement( 'head', ' ' );
$this->body = $this->document->createElement( 'body', ' ' );
}


public function
addStyleSheet ( $url, $media='all' )
{
$element = $this->document->createElement( 'link' );
$element->setAttribute( 'type', 'text/css' );
$element->setAttribute( 'href', $url );
$element->setAttribute( 'media', $media );
$this->styles[] = $element;
}


public function
addScript ( $url )
{
$element = $this->document->createElement( 'script', ' ' );
$element->setAttribute( 'type', 'text/javascript' );
$element->setAttribute( 'src', $url );
$this->scripts[] = $element;
}


public function
addMetaTag ( $name, $content )
{
$element = $this->document->createElement( 'meta' );
$element->setAttribute( 'name', $name );
$element->setAttribute( 'content', $content );
$this->metas[] = $element;
}


public function
setDescription ( $dec )
{
$this->addMetaTag( 'description', $dec );
}


public function
setKeywords ( $keywords )
{
$this->addMetaTag( 'keywords', $keywords );
}

public function
createElement ( $nodeName, $nodeValue=null )
{
return
$this->document->createElement( $nodeName, $nodeValue );
}

public function
assemble ( )
{
// Doctype creation
$doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML TRANSITIONAL 1.0//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';

// Create the head element
$title = $this->document->createElement( 'title', $this->title );
// Add stylesheets if needed
if ( is_array( $this->styles ))
foreach (
$this->styles as $element )
$this->head->appendChild( $element );
// Add scripts if needed
if( is_array( $this->scripts ))
foreach (
$this->scripts as $element )
$this->head->appendChild( $element );
// Add meta tags if needed
if ( is_array( $this->metas ))
foreach (
$this->metas as $element )
$this->head->appendChild( $element );
$this->head->appendChild( $title );

// Create the document
$html = $this->document->createElement( 'html' );
$html->setAttribute( 'xmlns', 'http://www.w3.org/1999/xhtml' );
$html->setAttribute( 'xml:lang', 'en' );
$html->setAttribute( 'lang', 'en' );
$html->appendChild( $this->head );
$html->appendChild( $this->body );


$this->document->appendChild( $html );
return
$doctype . $this->document->saveXML( );
}

}

?>

小型示例

<?php
$document
= new Document( );
$document->title = 'Hello';
$document->addStyleSheet( 'StyleSheets/main.css' );
$div = $document->createElement( 'div' );
$div->nodeValue = 'Hello, world!';
$div->setAttribute( 'style', 'color: red;' );
$document->body->appendChild( $div );
printf( '%s', $document->assemble( ) );
?>
qrworld.net
9 年前
在这篇文章 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