這似乎如此,但除非你指定的標誌是不是這樣的(這我想你不會在代碼中顯示你所做的事情)。只是如果您使用->asXML()
方法而不是通過字符串實現,SimpleXML只能將它返回給您。
讓我們來演示一下它的工作原理。
<!ENTITY n "noun (common) (futsuumeishi)">
所以我們選擇第一<pos>
因素,因爲它包含一個&n;
實體:
$xml = simplexml_load_file($file);
$pos = $xml->entry->sense->pos;
變量$pos
現在是<pos>
元素的SimpleXMLElement我從DTD選擇這個簡單的實體節點。讓我們將它輸出看到解析器確實與&n;
實體是什麼:
echo "SimpleXML value (string): ", $pos , "\n"
, "SimpleXML value (XML) : ", $pos->asXML(), "\n";
輸出是:
SimpleXML value (string): noun (common) (futsuumeishi)
SimpleXML value (XML) : <pos>&n;</pos>
這個例子說明,在&n;
仍然存在(<pos>&n;</pos>
),它只是它會在你訪問它的那一刻作爲字符串值進行擴展(noun (common) (futsuumeishi)
)。
順便提一下,XML規範在這裏說的是,解析器是否需要擴展這些實體。對於SimpleXML的設計,在閱讀字符串值時,這完全有望得到擴展。
你甚至可以通過指定LIBXML_NOENT
選項控制這一行爲:
$xml = simplexml_load_file($file, NULL, LIBXML_NOENT);
這實際上將你承擔那什麼,實體正在擴大,XML輸出不不包含實體不再:
SimpleXML value (string): noun (common) (futsuumeishi)
SimpleXML value (XML) : <pos>noun (common) (futsuumeishi)</pos>
所以現在雙問號怎麼辦,你在找什麼?那麼,PHP中的XML解析器實際上有一個實體模型是DOMDocument。它是SimpleXML的姊妹庫,在內部都共享相同的內存對象。下面是同一個對象的輸出(更準確地說:其唯一的子節點)爲這兩個模式,而不與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。
,否則這將是對不同的
<pos>&n;</pos>
<pos><![CDATA[&n;]]></pos>
字符串值的方式嗎?所以你要求的只是有限的意義。然而,這並不意味着我們無法處理這個問題,因此可以通過擴展SimpleXML來欺騙SimpleXML。假設每個只包含單個實體的子元素都應該返回。否則,標準的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) : <pos>&n;</pos>
&n;
因爲它是唯一的孩子現在保存在SimpleXMLElement的字符串轉換中。但是,僅僅因爲這個工作並不意味着你應該使用它,它打破了文本形式的解析XML和文檔模型意義上的XML之間的編碼邊界。
也許你只是在尋找DOMDocument?這是一個有更多細節的模型,如果有的話,您可以使用DOMEntityReference
。
是否有可能創建一個小樣本的XML和PHP代碼來顯示不良行爲?這將大大幫助他人理解問題並提出解決方案。 – IMSoP
@IMSoP:好評,最終沒有多少意義,儘管這是可能的。只是留下了廣泛的答案。 – hakre
[PHP SimpleXML獲取innerXML]的可能重複(http://stackoverflow.com/questions/1937056/php-simplexml-get-innerxml) – hakre