PHP:在没有CDATA的情况下将HTML保留在XML节点内

时间:2017-04-10 08:16:45

标签: php html xml simplexml-load-string

我有一个像这样的xml:

<father>
  <son>Text with <b>HTML</b>.</son>
</father>

我使用simplexml_load_string将其解析为SimpleXmlElement。然后我得到这样的节点

$xml->father->son->__toString(); //output: "Text with .", but expected "Text with <b>HTML</b>."

我需要处理简单的HTML,例如: xml中的<b>text</b><br/>由许多用户发送。

我的问题是,我不能让他们使用CDATA因为他们无法正确处理它,而且他们已经习惯了没有。 此外,如果可能,我不想要编辑文件,因为信息需要是用户发送的信息。

函数simplexml_load_string简单地删除HTML节点内的任何内容和HTML节点本身。 我如何保留信息?

为了解决这个问题,我使用了@XhW解释的asXml:

$tmp = $xml->father->son->asXml(); //<son>Text with <b>HTML</b>.</son>

我刚添加了一个preg_match来擦除节点。

1 个答案:

答案 0 :(得分:1)

CDATA部分是一个字符节点,就像文本节点一样。但它的编码/解码效果较差。实际上,这主要是一个缺点。从好的方面来看,CDATA部分中的某些内容对于人类来说可能更具可读性,并且在特殊情况下允许某些BC。 (想想HTML脚本标签。)

对于XML API,它们几乎相同。这是一个小的DOM示例(SimpleXML摘要很多)。

$document = new DOMDocument();
$father = $document->appendChild(
  $document->createElement('father')
);
$son = $father->appendChild(
  $document->createElement('son')
);
$son->appendChild(
  $document->createTextNode('With <b>HTML</b><br>It\'s so nice.')
);
$son = $father->appendChild(
  $document->createElement('son')
);
$son->appendChild(
  $document->createCDataSection('With <b>HTML</b><br>It\'s so nice.')
);

$document->formatOutput = TRUE;
echo $document->saveXml();

输出:

<?xml version="1.0"?>
<father>
  <son>With &lt;b&gt;HTML&lt;/b&gt;&lt;br&gt;It's so nice.</son>
  <son><![CDATA[With <b>HTML</b><br>It's so nice.]]></son>
</father>

正如您所看到的,它们的序列化方式截然不同 - 但从API视图来看,它们基本上是可交换的。如果你正在使用XML解析器,那么你得到的值在两种情况下应该是相同的。

所以第一种可能性就是让HTML片段存储在一个字符节点中。它只是外部XML文档本身的字符串值。

另一种方式是使用XHTML。 XHTML是XML兼容的HTML。您可以混合匹配不同的XML格式,因此您可以将XHTML片段作为外部XML的一部分添加。

这似乎就是你所接受的。但SimpleXML在混合节点方面存在一些问题。所以这是一个如何在DOM中阅读它的例子。

$xml = <<<'XML'
<father>
  <son>With <b>HTML</b><br/>It's so nice.</son>
</father>
XML;

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

$result = '';
foreach ($xpath->evaluate('/father/son[1]/node()') as $child) {
  $result .= $document->saveXml($child);
}
echo $result;

输出:

With <b>HTML</b><br/>It's so nice.

基本上,您需要将son元素的每个子元素保存为XML。

SimpleXML内部基于相同的DOM库。这允许您将SimpleXMLElement转换为DOM节点。从那里,您可以再次将每个孩子保存为XML。

$father = new SimpleXMLElement($xml);
$sonNode = dom_import_simplexml($father->son);
$document = $sonNode->ownerDocument;

$result = '';
foreach ($sonNode->childNodes as $child) {
  $result .= $document->saveXml($child);
}
echo $result;