获取xml子项而不替换PHP中的html实体

时间:2012-02-29 19:44:52

标签: php xml

我有这段代码:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
$strXml = '
<root>
<kid><div>ABC&#8226;&#62;</div></kid>
<kid2>DEF</kid2>
</root>';   

$objXml = new SimpleXMLElement($strXml);
$arrNodes = $objXml->xpath('/root/*');
foreach($arrNodes as $objNode) {
    /* @var $objNode SimpleXMLElement */
    echo $objNode->asXML(); 
}

代码提取根的第一个子节点并显示内容。问题是html实体被转换为字符。代码是否有任何方式输出初始XML内容而没有任何转换?

3 个答案:

答案 0 :(得分:1)

  

代码是否有任何方式输出初始XML内容而没有任何转换?

没有

旁白:你为什么关心?他们是同一个角色。

答案 1 :(得分:0)

SimpleXML / DOMDocument / etc将始终转换这些实体,因为编号实体不是有效的XML。

所以:

  • 史诗搜索和替换。
  • 或者修复生成XML的内容?

答案 2 :(得分:0)

这让我觉得这是一种非常奇怪的行为,而且我没有运气搜索信息。

它似乎影响了所有相关的XML stuff。值得注意的是,一旦解析了XML,字符就会存储为常规字符:

php > print_r($objXml);
SimpleXMLElement Object
(
    [kid] => SimpleXMLElement Object
        (
            [div] => ABC•>
        )

    [kid2] => DEF
)

...当XML转换为文本时,它们被写为实体。我猜测所有东西都使用相同的内部例程来转换为文本。

如果你真的需要这个功能,你可以创建自己的功能来逃避角色,如下所示:

// function to escape some utf8 characters with xml character reference 
function xmlCharEncode($string) {

  $out = '';

  $len = mb_strlen($string, 'UTF-8');

  for ($i = 0; $i < $len; $i++) {

    $char = mb_substr($string, $i, 1, 'UTF-8');

    $convmap = array(
      60,  60, 0, 0xffff, // <
      62,  62, 0, 0xffff, // >
      38,  38, 0, 0xffff, // ampersand
      // you may want to filter quotes or other characters here
      127, 0xffff, 0, 0xffff, // everything after basic latin
    );

    $enc = mb_encode_numericentity($char, $convmap, 'UTF-8');

    $out .= $enc;

  }

  return $out;

}

...然后使用XMLReader和XMLWriter使用自定义字符转义例程编写XML:

// read and write your xml string

$r = new XMLReader();
$w = new XMLWriter();
$r->xml($strXml);
$w->openMemory();

while($r->read()) {

  switch ($r->nodeType) {

    // write elements, attributes, and text nodes

    case XMLReader::ELEMENT:
      $w->startElement($r->name);
      while ($r->moveToNextAttribute()) {
        echo $w->outputMemory(true);
        $w->writeAttribute($r->name, $r->value);
      }
      break;

    case XMLReader::END_ELEMENT:
      $w->endElement();
      break;

    case XMLReader::TEXT:
      $w->writeRaw(xmlCharEncode($r->value)); // the magic happens here
      break;

  }

  echo $w->outputMemory(true);

}

我并不是真的相信这是值得的,但至少你知道可以采取什么样的措施来实现这个目标。

顺便说一下,这将适用于您的原始示例。