10

我需要answer在这段 XML 中获取 HTML 内容:

<qa>
 <question>Who are you?</question>
 <answer>Who who, <strong>who who</strong>, <em>me</em></answer>
</qa>

所以我想得到字符串“谁谁,<strong>谁谁</strong>,<em>我</em>”。

如果我有answeras a SimpleXMLElement,我可以调用asXML()获取“<answer>Who who,<strong>who who</strong>,<em>me</em></answer>”,但如何获取内部 XML没有元素本身包裹的元素?

我更喜欢不涉及字符串函数的方法,但如果这是唯一的方法,那就这样吧。

4

11 回答 11

13
function SimpleXMLElement_innerXML($xml)
  {
    $innerXML= '';
    foreach (dom_import_simplexml($xml)->childNodes as $child)
    {
        $innerXML .= $child->ownerDocument->saveXML( $child );
    }
    return $innerXML;
  };
于 2011-08-20T01:33:32.037 回答
6

这行得通(虽然它看起来真的很蹩脚):

echo (string)$qa->answer;
于 2010-09-02T04:05:17.393 回答
5

据我所知,没有内置的方法可以做到这一点。我建议尝试SimpleDOM,这是一个扩展 SimpleXMLElement 的 PHP 类,它为大多数常见问题提供了方便的方法。

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();

否则,我看到了两种方法。第一个是将您的转换SimpleXMLElementDOMNodethen 循环,childNodes以构建 XML。另一种是调用asXML()然后使用字符串函数来删除根节点。但请注意,asXML()有时可能会返回实际上位于调用它的节点之外的标记,例如 XML 序言或处理指令。

于 2009-12-21T03:22:39.763 回答
4

最直接的解决方案是使用简单的 XML 实现自定义 get innerXML:

function simplexml_innerXML($node)
{
    $content="";
    foreach($node->children() as $child)
        $content .= $child->asXml();
    return $content;
}

在您的代码中,替换$body_content = $el->asXml();$body_content = simplexml_innerXML($el);

但是,您也可以切换到另一个 API,该 API 提供了 innerXML(您正在寻找的内容)和 outerXML(您现在得到的内容)之间的区别。Microsoft Dom 库提供了这种区别,但不幸的是 PHP DOM 没有。

我发现 PHP XMLReader API 提供了这种区别。请参阅 readInnerXML()。虽然这个 API 有一种完全不同的处理 XML 的方法。尝试一下。

最后,我要强调的是,XML 并不是要将数据提取为子树,而是提取为值。这就是为什么您在寻找正确的 API 时遇到困难的原因。将 HTML 子树存储为值(并转义所有标签)而不是 XML 子树会更“标准”。还要注意一些 HTML 合成器并不总是与 XML 兼容(即
vs ,
)。无论如何,在实践中,您的方法对于编辑 xml 文件肯定更方便。

于 2011-06-13T05:44:26.827 回答
1

我会扩展 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();
于 2012-08-24T08:26:29.720 回答
0
<?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)
于 2012-02-29T15:30:08.907 回答
0
    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;
    }
于 2013-10-04T19:12:22.703 回答
0

如果您不想删除 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);
}
于 2014-03-20T01:30:07.013 回答
0

您可以使用此功能:)

function innerXML( $node )
{
    $name = $node->getName();
    return preg_replace( '/((<'.$name.'[^>]*>)|(<\/'.$name.'>))/UD', "", $node->asXML() );
}
于 2014-06-19T06:14:27.037 回答
0

这是我创建的一个非常快速的解决方案:

function InnerHTML($Text)
{   
    return SubStr($Text, ($PosStart = strpos($Text,'>')+1), strpos($Text,'<',-1)-1-$PosStart);
}

echo InnerHTML($yourXML->qa->answer->asXML());
于 2020-12-04T10:25:29.273 回答
-2

使用正则表达式你可以做到这一点

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);
于 2009-12-20T21:17:18.047 回答