Pregunta

necesito para obtener el contenido HTML de answer en este poco de XML:

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

Así que quiero obtener la cadena "¿Quién que, que quien , me ".

Si tengo el answer como SimpleXMLElement, puedo llamar asXML() para conseguir " Quién que, que quien , me ", pero cómo obtener el código XML interno de un elemento sin el propio elemento envuelto alrededor de él?

Yo prefiero maneras que no impliquen funciones de cadena, pero si esa es la única manera, que así sea.

¿Fue útil?

Solución

A lo mejor de mi conocimiento, no está incorporado manera de conseguir eso. Recomiendo probar SimpleDOM , que es una clase PHP que se extiende SimpleXMLElement que ofrece métodos convenientes para la mayoría de los problemas comunes.

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

De lo contrario, veo dos formas de hacerlo. La primera sería la de convertir su SimpleXMLElement a un DOMNode continuación, un bucle sobre su childNodes para construir el XML. El otro sería llamar asXML() a continuación, utilizar funciones de cadena para eliminar el nodo raíz. Atención sin embargo, a veces puede volver asXML() marcado que en realidad es fuera del nodo que fue llamado, como prólogo XML o instrucciones de procesamiento.

Otros consejos

function SimpleXMLElement_innerXML($xml)
  {
    $innerXML= '';
    foreach (dom_import_simplexml($xml)->childNodes as $child)
    {
        $innerXML .= $child->ownerDocument->saveXML( $child );
    }
    return $innerXML;
  };

Esto funciona (aunque parece muy escaso):

echo (string)$qa->answer;

solución más sencilla consiste en aplicar personalizado Descarga InnerXml con sencillo XML:

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

En su código, reemplace $body_content = $el->asXml(); con $body_content = simplexml_innerXML($el);

Sin embargo, también se puede cambiar a otra API que ofrece distinción entre InnerXml (lo que busca) y OuterXml (lo que se obtiene por ahora). Microsoft Dom libary ofrece esta distinción, pero por desgracia PHP DOM no.

He encontrado que PHP XMLReader API ofrece esta Distinción. Ver ReadInnerXml (). Aunque esta API tiene un enfoque muy diferente al procesamiento de XML. Probarlo.

Por último, quiero subrayar que XML no tiene la intención de extraer datos como subárboles sino más bien como valor. Es por eso que toparse con problemas para encontrar la API derecha. Sería más 'estándar' para almacenar subárbol HTML como un valor (y escapar de todas las etiquetas) en lugar de sub-árbol XML. También ten en cuenta que algunos synthax HTML no siempre son compatibles XML (es decir
vs, España). De todos modos, en la práctica, que se acerca es definitivamente más conveniente para editar el archivo XML.

Tendría extender la clase 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());
    }
}

y luego usarlo como esto:

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>"));      
?>

Después de que busco por un tiempo, no tengo solución de la satisfacción. Así que escribí mi propia función. Esta función obtendrá exactamente el contenido innerXml (incluyendo espacios en blanco, por supuesto). Para usarlo, pasar el resultado de la función asXML(), como este getInnerXml($e->asXML()). Este trabajo de la función de los elementos con muchos prefijos así (como mi caso, ya que no pude encontrar métodos actuales que realizan conversión en todos los nodos hijos de diferentes prefijos).

Salida:

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;
    }

Si no quiere despojar sección CDATA, comente las líneas 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);
}

Sólo puede utilizar esta función:)

function innerXML( $node )
{
    $name = $node->getName();
    return preg_replace( '/((<'.$name.'[^>]*>)|(<\/'.$name.'>))/UD', "", $node->asXML() );
}

usando expresiones regulares que podría hacer esto

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top