如何在php DOMDocument中导入XML字符串

Pas*_*Qyy 7 php xml xhtml simplexml domdocument

例如,我创建了DOMDocument这样的:

<?php

$implementation = new DOMImplementation();

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

$document = $implementation->createDocument('', '', $dtd);

$elementHtml     = $document->createElement('html');
$elementHead     = $document->createElement('head');
$elementBody     = $document->createElement('body');
$elementTitle    = $document->createElement('title');
$textTitre       = $document->createTextNode('My bweb page');
$attrLang        = $document->createAttribute('lang');
$attrLang->value = 'en';

$document->appendChild($elementHtml);
$elementHtml->appendChild($elementHead);
$elementHtml->appendChild($attrLang);
$elementHead->appendChild($elementTitle);
$elementTitle->appendChild($textTitre);
$elementHtml->appendChild($elementBody);
Run Code Online (Sandbox Code Playgroud)

那么,现在,如果我有一些像这样的xhtml字符串:

<?php
$xhtml = '<h1>Hello</h1><p>World</p>';
Run Code Online (Sandbox Code Playgroud)

如何在<body>我的节点中导入它DOMDocument

就目前而言,我发现的唯一解决方案是这样的:

<?php
$simpleXmlElement = new SimpleXMLElement($xhtml);

$domElement = dom_import_simplexml($simpleXmlElement);

$domElement = $document->importNode($domElement, true);

$elementBody->appendChild($domElement);
Run Code Online (Sandbox Code Playgroud)

这个解决方案对我来说似乎非常糟糕,并且会产生一些问题,就像我尝试使用这样的字符串时:

<?php
$xhtml = '<p>Hello&nbsp;World</p>';
Run Code Online (Sandbox Code Playgroud)

好吧,我可以通过转换Unicode实体中的xhtml实体来绕过这个问题,但它太丑了......

有帮助吗?

谢谢提前!

相关问题:

Gor*_*don 9

问题是DOM不知道它应该考虑XHTML DTD,除非您根据它验证了文档.除非你这样做,否则DOM不知道DTD中定义的任何实体,也不知道其中的任何其他规则.幸运的是,我们已经解决了如何在其他问题中进行验证,因此您可以使用这些知识

$document->validate(); // anywhere before importing the other DOM
Run Code Online (Sandbox Code Playgroud)

然后导入

$fragment = $document->createDocumentFragment();
$fragment->appendXML('<h1>Hello</h1><p>Hello&nbsp;World</p>');
$document->getElementsByTagName('body')->item(0)->appendChild($fragment);
$document->formatOutput = TRUE;
echo $document->saveXml();
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0"?>
<!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" lang="en" xml:lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>My bweb page</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>Hello&nbsp;World</p>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

将XML导入另一个DOM的另一种方法是使用

$one = new DOMDocument;
$two = new DOMDocument;
$one->loadXml('<root><foo>one</foo></root>');
$two->loadXml('<root><bar><sub>two</sub></bar></root>');
$bar = $two->documentElement->firstChild; // we want to import the bar tree
$one->documentElement->appendChild($one->importNode($bar, TRUE));
echo $one->saveXml();
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0"?>
<root><foo>one</foo><bar><sub>two</sub></bar></root>
Run Code Online (Sandbox Code Playgroud)

但是,这不能用

<h1>Hello</h1><p>Hello&nbsp;World</p>
Run Code Online (Sandbox Code Playgroud)

因为当您将文档加载到DOM中时,DOM将覆盖您在文档之前告诉它的所有内容.因此,当使用load时,libxml(以及SimpleXml,DOM和XMLReader)确实(不)知道你的意思是XHTML.并且它不知道其中定义的任何实体,而是会对它们进行模糊处理.但即使字符串不包含实体,它也不是有效的XML,因为它缺少根节点.这就是你使用片段的原因.

  • @Service和@G.Qyy:另一种选择可能是[取消注册](http://de.php.net/manual/en/function.stream-wrapper-unregister.php)[常规HTTP](http://de.php.net /manual/en/wrappers.php)[stream wrapper](http://de.php.net/manual/en/book.stream.php)并将其替换为您自己的实现,该实现从本地副本读取DTD. (2认同)