当前位置: 首页 > 工具软件 > SimpleXML > 使用案例 >

php xml扩展,php-SimpleXML,请不要扩展实体

南门新荣
2023-12-01

我正在使用SimpleXML尝试使用

我曾考虑过“预解析” XML文件,以在将文件内容传递给XML解析器之前去掉

(请原谅上面的任何错误术语;我已经很长时间没有完成此级别的XML了.)

解决方法:

看起来似乎是这样,但事实并非如此(除非您指定标志,尽管您没有在代码中显示您所做的事情,但我猜您不会这么做).仅当您使用-> asXML()方法而不通过to-string-implementation时,SimpleXML才能将其返回给您.

让我们做一些例子来演示它是如何工作的.我从DTD中选择了以下简单实体:

因此,让我们选择第一个< pos>元素,因为它包含& n;实体:

$xml = simplexml_load_file($file);

$pos = $xml->entry->sense->pos;

变量$pos现在是< pos>的SimpleXMLElement.元素节点.让我们输出它,以查看解析器对& n;做些什么.实体:

echo "SimpleXML value (string): ", $pos , "\n"

, "SimpleXML value (XML) : ", $pos->asXML(), "\n";

输出为:

SimpleXML value (string): noun (common) (futsuumeishi)

SimpleXML value (XML) : &n;

如本例所示,& n;仍然在那儿(< pos& n;< / pos>),只是当您将其作为字符串值(名词(普通)(futsuumeishi))访问时,它将被扩展.

顺便说一句,这完全可以,XML规范在这里说,是否扩展这些实体取决于解析器.对于SimpleXML的设计目的,在读取字符串值时,这完全可以扩展.

您甚至可以通过指定LIBXML_NOENT选项来控制此行为:

$xml = simplexml_load_file($file, NULL, LIBXML_NOENT);

这实际上将执行您假设的操作,现在扩展实体,XML输出不再包含该实体:

SimpleXML value (string): noun (common) (futsuumeishi)

SimpleXML value (XML) : noun (common) (futsuumeishi)

因此,现在出现双重问号了,该怎么做?嗯,PHP中的XML解析器实际上是实体模型,它是DOMDocument.它是SimpleXML的姊妹库,内部都共享相同的内存对象.这是不使用LIBXML_NOENT和使用LIBXML_NOENT的两种模式的同一对象(更精确的是:其唯一的子节点)的输出:

Mode 1:

DOMDocument Class : DOMEntityReference

DOMDocument value(XML) : &n;

DOMDocument ->nodeName : n

Mode 2 (LIBXML_NOENT):

DOMDocument Class : DOMText

DOMDocument value(XML) : noun (common) (futsuumeishi)

DOMDocument ->nodeName : #text

这是由以下代码创建的,这些代码应使给定输出背后的内容更清晰可见:

$node = dom_import_simplexml($pos);

$doc = $node->ownerDocument;

$entity = $node->firstChild;

echo "DOMDocument Class : ", get_class($entity) , "\n"

, "DOMDocument value(XML) : ", $doc->saveXML($entity), "\n"

, "DOMDocument ->nodeName : ", $entity->nodeName , "\n";

如所写,它是一个姊妹库,而dom_import_simplexml将$pos变成一个DOMElement,我们需要遍历该子元素的子元素,我们知道这是有问题的实体引用.

因此,现在这已经很有意义了:由于SimpleXML无法表示实体引用,因此只能提供扩展的字符串值或包含实体的XML.

否则,如何区别的字符串值

&n;

?因此,您所要求的只有有限的意义.但这并不意味着我们无法处理,因此可以通过扩展SimpleXML来欺骗SimpleXML.假设每个仅包含单个实体的子元素都应返回so.否则,应使用标准的SimpleXML stringyfication:

/**

* Class EntityPreserveXML

*/

class EntityPreserveXML extends SimpleXMLElement

{

/**

* @return string

*/

public function __toString()

{

$dom = dom_import_simplexml($this);

if (

!$dom instanceof DOMElement

|| $dom->childNodes->length !== 1

|| ! $dom->firstChild instanceof DOMEntityReference

) {

return parent::__toString();

}

return $dom->ownerDocument->saveXML($dom->firstChild);

}

}

让我们在上面的示例中运行它:

require('EntityPreserveXML.php');

$xml = simplexml_load_file($file, 'EntityPreserveXML');

$pos = $xml->entry->sense->pos;

echo "SimpleXML value (string): ", $pos , "\n"

, "SimpleXML value (XML) : ", $pos->asXML(), "\n";

SimpleXML现在正在使用扩展类,该扩展类将按预期提供:

SimpleXML value (string): &n;

SimpleXML value (XML) : &n;

& n;因为它是唯一的孩子,所以现在保留在SimpleXMLElement的字符串转换中.但是,仅因为这种方法不一定意味着您应该使用它,否则它就打破了文本形式的已解析XML与文档模型意义上的XML之间的编码边界.

可能您只是在寻找DOMDocument?这是一个具有更多详细信息的模型,您可以从中使用DOMEntityReferences(如果有).

标签:php,xml,simplexml

来源: https://codeday.me/bug/20191011/1889959.html

 类似资料: