PHP的SimpleXML GET innerXML
题
我需要得到answer
的HTML内容在此位XML的:
<qa>
<question>Who are you?</question>
<answer>Who who, <strong>who who</strong>, <em>me</em></answer>
</qa>
所以,我想要得到的字符串 “谁是谁,谁谁,我的。”
如果我有answer
作为SimpleXMLElement
,我可以打电话asXML()
得到 “<答案>谁是谁,谁谁,我的回答>”,但如何获得的元件的内XML的周围没有包裹元件本身?
我宁愿不涉及字符串函数的方式,但如果这是唯一的办法,就这样吧。
解决方案
据我所知,目前没有内置的方式来获取。我建议尝试 SimpleDOM ,这是提供了最方便的方法PHP类扩展的SimpleXMLElement的常见问题。
include 'SimpleDOM.php';
$qa = simpledom_load_string(
'<qa>
<question>Who are you?</question>
<answer>Who who, <strong>who who</strong>, <em>me</em></answer>
</qa>'
);
echo $qa->answer->innerXML();
另外,我觉得那样做有两种方式。第一是你SimpleXMLElement
在其DOMNode
构建XML转换为childNodes
然后循环。其他将调用asXML()
然后使用字符串函数以除去根节点。注意虽然,asXML()
有时返回标记,实际上是 的节点的它是从调用,如XML序言或处理指令之外。
其他提示
function SimpleXMLElement_innerXML($xml)
{
$innerXML= '';
foreach (dom_import_simplexml($xml)->childNodes as $child)
{
$innerXML .= $child->ownerDocument->saveXML( $child );
}
return $innerXML;
};
这工作(尽管它似乎真的跛脚):
echo (string)$qa->answer;
最直接的解决方案是实现自定义得到innerXML用简单的XML:
function simplexml_innerXML($node)
{
$content="";
foreach($node->children() as $child)
$content .= $child->asXml();
return $content;
}
在您的代码,替换$body_content = $el->asXml();
$body_content = simplexml_innerXML($el);
不过,您也可以切换到提供和outerXML(你会得到什么现在)innerXML区分(你在找什么)另一个API。微软大教堂libary提供这一区分,但是不幸的是PHP DOM没有。
我发现PHP的XMLReader API提供了这种distintion。见readInnerXML()。虽然这个API有相当不同的方法来处理XML。尝试。
最后,我想强调的是,XML不意味着提取的数据作为子树而是作为值。这就是为什么你运行陷入困境找到合适的API。这将是更“标准”来存储HTML子树的值(和逃避所有标签),而不是XML树。另外注意的是一些HTML synthax并不总是XML兼容(即点击VS,搜索)。在实践中,无论如何,你的做法是绝对是编辑XML文件更加方便。
我将具有延长的SimpleXMLElement类:
class MyXmlElement extends SimpleXMLElement{
final public function innerXML(){
$tag = $this->getName();
$value = $this->__toString();
if('' === $value){
return null;
}
return preg_replace('!<'. $tag .'(?:[^>]*)>(.*)</'. $tag .'>!Ums', '$1', $this->asXml());
}
}
和然后使用它是这样的:
echo $qa->answer->innerXML();
<?php
function getInnerXml($xml_text) {
//strip the first element
//check if the strip tag is empty also
$xml_text = trim($xml_text);
$s1 = strpos($xml_text,">");
$s2 = trim(substr($xml_text,0,$s1)); //get the head with ">" and trim (note that string is indexed from 0)
if ($s2[strlen($s2)-1]=="/") //tag is empty
return "";
$s3 = strrpos($xml_text,"<"); //get last closing "<"
return substr($xml_text,$s1+1,$s3-$s1-1);
}
var_dump(getInnerXml("<xml />"));
var_dump(getInnerXml("<xml / >faf < / xml>"));
var_dump(getInnerXml("<xml >< / xml>"));
var_dump(getInnerXml("<xml>faf < / xml>"));
var_dump(getInnerXml("<xml > faf < / xml>"));
?>
在我搜索了一段时间,我没有满足解决方案。所以我写了我自己的函数。
该功能将得到确切的innerXml
内容(包括空格,当然)。
要使用它,通过功能asXML()
的结果,这样getInnerXml($e->asXML())
。这对于许多前缀以及要素功能的工作(如我的情况,因为我无法找到任何目前的方法是做不同前缀的所有子节点的转换)。
输出:
string '' (length=0)
string '' (length=0)
string '' (length=0)
string 'faf ' (length=4)
string ' faf ' (length=6)
function get_inner_xml(SimpleXMLElement $SimpleXMLElement)
{
$element_name = $SimpleXMLElement->getName();
$inner_xml = $SimpleXMLElement->asXML();
$inner_xml = str_replace('<'.$element_name.'>', '', $inner_xml);
$inner_xml = str_replace('</'.$element_name.'>', '', $inner_xml);
$inner_xml = trim($inner_xml);
return $inner_xml;
}
如果你不想要去除CDATA部分,注释行6-8。
function innerXML($i){
$text=$i->asXML();
$sp=strpos($text,">");
$ep=strrpos($text,"<");
$text=trim(($sp!==false && $sp<=$ep)?substr($text,$sp+1,$ep-$sp-1):'');
$sp=strpos($text,'<![CDATA[');
$ep=strrpos($text,"]]>");
$text=trim(($sp==0 && $ep==strlen($text)-3)?substr($text,$sp+9,-3):$text);
return($text);
}
您可以只使用此功能:)
function innerXML( $node )
{
$name = $node->getName();
return preg_replace( '/((<'.$name.'[^>]*>)|(<\/'.$name.'>))/UD', "", $node->asXML() );
}
使用正则表达式,你可以做到这一点。
preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);