Question

Je dois obtenir le contenu HTML de answer dans ce bit XML:

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

Je veux la chaîne "Qui qui, qui qui , me ".

Si je le answer comme SimpleXMLElement, je peux appeler asXML() pour obtenir " Qui qui, qui qui , me ", mais comment obtenir le XML interne d'un élément sans l'élément lui-même enroulé autour de lui?

Je préfère des moyens qui ne concernent pas les fonctions de chaîne, mais si c'est la seule façon, soit.

Était-ce utile?

La solution

Au meilleur de ma connaissance, il n'y a pas intégré de manière à obtenir. Je recommande d'essayer SimpleDOM , qui est une classe PHP extension SimpleXMLElement qui offre des méthodes pratiques pour la plupart des problèmes communs.

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

Dans le cas contraire, je vois deux façons de le faire. La première serait de convertir votre SimpleXMLElement à un DOMNode puis une boucle sur son childNodes pour construire le XML. L'autre serait d'appeler asXML() puis utiliser les fonctions de chaîne pour supprimer le nœud racine. Attention cependant, asXML() peut parfois revenir le balisage qui est en fait à l'extérieur du nœud, il a été appelé à partir, comme les instructions de Prolog ou traitement XML.

Autres conseils

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

Cela fonctionne (bien qu'il semble vraiment boiteux):

echo (string)$qa->answer;

solution la plus simple consiste à mettre en œuvre avec XML simple, obtenir la coutume InnerXml:

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

Dans votre code, remplacez $body_content = $el->asXml(); avec $body_content = simplexml_innerXML($el);

Cependant, vous pouvez également passer à une autre API qui offre la distinction entre InnerXml (ce que vous cherchez) et OuterXml (ce que vous obtenez pour l'instant). Microsoft Dom libary offre cette distinction mais malheureusement PHP DOM ne fonctionne pas.

J'ai trouvé que l'API PHP XMLReader offre ce distintion. Voir readInnerXML (). Bien que cette API a une approche tout à fait différente de XML de traitement. Essayez.

Enfin, je tiens à souligner que XML ne vise pas à extraire des données comme sous-arbres, mais plutôt comme valeur. Voilà pourquoi vous courir dans la difficulté à trouver l'API droite. Il serait plus « standard » pour stocker HTML sous-arbre en tant que valeur (et échapper à tous les tags) plutôt que de sous-arborescence XML. Méfiez-vous également que certains synthaxe HTML ne sont pas toujours compatibles XML (à savoir
vs,
). Quoi qu'il en soit, dans la pratique, vous approche est certainement plus pratique pour éditer le fichier xml.

Je devrais étendre la classe 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());
    }
}

et puis l'utiliser comme ceci:

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

Après je recherche pendant un certain temps, je suis pas de solution satisfaire. Alors, je l'ai écrit ma propre fonction. Cette fonction se précise la teneur en innerXml (y compris l'espace blanc, bien sûr). Pour l'utiliser, de transmettre le résultat de la fonction asXML(), comme celui-ci getInnerXml($e->asXML()). Ce travail de fonction pour les éléments avec de nombreux préfixes aussi bien (comme mon cas, comme je ne pouvais pas trouver toutes les méthodes actuelles qui font la conversion sur tous nœud enfant de différents préfixes).

Sortie:

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 vous ne voulez pas dépouiller la section CDATA, commentez les lignes 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);
}

Vous pouvez simplement utiliser cette fonction:)

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

à l'aide regex vous pouvez le faire

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top