DOMDocument appendXML带有特殊字符

Mar*_*nix 1 html php domdocument

我正在从我的数据库中检索一些html字符串,我想将这些字符串解析为我的DOMDocument.问题是,DOMDocument会在特殊字符处发出警告.

警告:DOMDocumentFragment :: appendXML()[domdocumentfragment.appendxml]:实体:第2行:解析器错误:实体'nbsp'未在第189行的page.php中定义

我想知道为什么,我想知道如何解决这个问题.这是我页面的一些代码片段.我该如何解决这些警告?

$doc = new DOMDocument();

// .. create some elements first, like some divs and a h1 ..

while($row = mysql_fetch_array($result))
{
    $messageEl = $doc->createDocumentFragment();
    $messageEl->appendXML($row['message']); // gives it's warnings here!

    $otherElement->appendChild($messageEl);
}

echo $doc->saveHTML();
Run Code Online (Sandbox Code Playgroud)

我还发现了一些关于验证的内容,但是当我应用它时,我的页面将不再加载.我试过的代码是这样的.

$implementation = new DOMImplementation();
$dtd = $implementation->createDocumentType('html','-//W3C//DTD XHTML 1.0 Transitional//EN','http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd');

$doc = $implementation->createDocument('','',$dtd);
$doc->validateOnParse = true;
$doc->formatOutput = true;

// in the same whileloop, I used the following:
$messageEl = $doc->createDocumentFragment();
$doc->validate(); // which stopped my code, but error- and warningless.
$messageEl->appendXml($row['message']);
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Tom*_*lak 6

 XML中没有.那有一个实际的唯一字符实体名称定义(而不是使用数字参考)是&,<,>,"'.

这意味着你必须使用非破坏空间的数字等价物,即 或(十六进制) .

如果您尝试将HTML保存到XML容器中,请将其另存为文本.HTML和XML可能看起来很相似,但它们非常不同.appendXML()期望格式良好的XML作为参数.使用该nodeValue属性,它将对HTML字符串进行XML编码,而不会发出任何警告.

// document fragment is completely unnecessary
$otherElement->nodeValue = $row['message'];
Run Code Online (Sandbox Code Playgroud)


Gor*_*don 5

这是一个棘手的问题,因为它实际上是多个问题.

就像Tomalak指出的那样, XML中没有.所以你做了正确的事情来指定DOMImplementation,因为在XHTML中有 .但是,要让DOM知道文档是XHTML,您需要加载并验证DTD.DTD位于

http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
Run Code Online (Sandbox Code Playgroud)

但由于每天有数百万个请求到该页面,W3C决定阻止访问该页面,除非在请求中发送了UserAgent.要提供UserAgent,您必须创建自定义流上下文.

在代码中:

// make sure DOM passes a User Agent when it fetches the DTD
libxml_set_streams_context(
    stream_context_create(
        array(
            'http' => array(
                'user_agent' => 'PHP libxml agent',
            )
        )
    )
);

// specify the implementation
$imp = new DOMImplementation;

// create a DTD (here: for XHTML)
$dtd = $imp->createDocumentType(
    'html',
    '-//W3C//DTD XHTML 1.0 Transitional//EN',
    'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
);

// then create a DOMDocument with the configured DTD
$dom = $imp->createDocument(NULL, "html", $dtd);
$dom->encoding = 'UTF-8';
$dom->validate();

$fragment = $dom->createDocumentFragment();
$fragment->appendXML('
    <head><title>XHTML test</title></head>
    <body><p>Some text with a &nbsp; entity</p></body>
    '
);
$dom->documentElement->appendChild($fragment);
$dom->formatOutput = TRUE;
echo $dom->saveXml();
Run Code Online (Sandbox Code Playgroud)

这仍然需要一些时间来完成(不要问我为什么)但最终,你会得到(重新格式化为SO)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC 
    "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>XHTML test</title>
    </head>
    <body>
        <p>Some text with a &nbsp; entity</p>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

另请参阅DOMDocument :: validate()问题