2009-12-20 1 views
8

Ich brauche die HTML-Inhalte von answer in diesem Bit von XML zu erhalten:PHP SimpleXML bekommen InnerXml

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

Deshalb möchte ich die Zeichenfolge bekommen „Wer ist wer, <starke>, die die </strong >, <em> mich </em > ".

Wenn ich die answer als eine SimpleXMLElement haben, kann ich asXML() nennen "<Antwort> Wer ist wer, <starke>, die die </strong >, <em> mich </em > </Antwort >" zu bekommen, aber wie bekomme ich das innere XML eines Elements, ohne dass das Element selbst darum gewickelt ist?

Ich würde es vorziehen, Wege, die keine String-Funktionen beinhalten aber wenn das der einzige Weg ist, es so sein.

Antwort

5

Nach bestem Wissen und Gewissen tun könnten, wird es nicht integrierte Möglichkeit, das zu bekommen. Ich würde empfehlen, SimpleDOM zu versuchen, was eine PHP-Klasse ist, die SimpleXMLElement erweitert und bequeme Methoden für die meisten gängigen Probleme bietet.

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

Ansonsten sehe ich zwei Möglichkeiten, das zu tun. Die erste wäre, Ihre SimpleXMLElement in eine DOMNode konvertieren dann Schleife über seine childNodes, um das XML zu bauen. Der andere wäre, asXML() aufzurufen, dann verwenden Sie Zeichenfolgenfunktionen, um den Wurzelknoten zu entfernen. obwohl Achtung, asXML() kann manchmal Markup zurück, die tatsächlich außerhalb des Knotens ist es aus, wie XML-Prolog oder Verarbeitungshinweise aufgerufen wurde.

-2

mit regex Sie diesen

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match); 
$result=$match[0]; 
print_r($result); 
+0

Dies ist definitiv der falsche Anwendungsfall für regex. Man sollte es niemals für das XML/Dom-Parsing verwenden. Wenn man nicht über $ $ match [0] spricht, enthält es immer den vollen zu durchsuchenden Text. Und $ xml ist ein Objekt, kein String. –

5

Das funktioniert (obwohl es wirklich lahm scheint):

echo (string)$qa->answer; 
+0

Nicht lahm! Ich habe mich davor bewahrt, XML mit mehreren Variablen zu jonglieren. Ich habe lamer gesehen;) – rvdavid

4

einfachste Lösung ist InnerXml mit einfachen XML zu implementieren benutzerdefinierten erhalten:

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

in Ihrem Code ersetzt $body_content = $el->asXml(); mit $body_content = simplexml_innerXML($el);

Sie können jedoch auch auf eine andere API wechseln, die Unterscheidung zwischen InnerXml bietet (was Sie suchen) und outerXML (was du für jetzt bekommst). Microsoft Dom-Bibliothek bietet diese Unterscheidung, aber leider PHP DOM nicht.

fand ich, dass PHP XMLReader API dieses distintion bietet. Siehe readInnerXML(). Obwohl diese API einen ganz anderen Ansatz für die Verarbeitung von XML hat. Versuch es.

Abschließend möchte ich betonen, dass XML nicht extrahieren Daten als Teilstrukturen gemeint, sondern als Wert. Aus diesem Grund haben Sie Probleme, die richtige API zu finden. Es wäre "Standard", den HTML-Teilbaum als Wert zu speichern (und alle Tags zu entkommen) anstatt als XML-Teilbaum. Beachten Sie auch, dass einige HTML-Synthax nicht immer XML-kompatibel sind (d. H.
vs,
). Wie auch immer, in der Praxis ist es einfacher, die XML-Datei zu bearbeiten.

+0

Danke dafür, ein Problem obwohl, das Codebeispiel ist leicht gebrochen, $ Knoten ist nicht definiert. –

12
function SimpleXMLElement_innerXML($xml) 
    { 
    $innerXML= ''; 
    foreach (dom_import_simplexml($xml)->childNodes as $child) 
    { 
     $innerXML .= $child->ownerDocument->saveXML($child); 
    } 
    return $innerXML; 
    }; 
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>"));  
?> 

Nachdem ich für eine Weile suchen, habe ich keine Lösung erfüllen. Also habe ich meine eigene Funktion geschrieben. Diese Funktion wird genau den innerXml Inhalt (einschließlich Leerzeichen, natürlich) erhalten. Um es zu verwenden, übergeben Sie das Ergebnis der Funktion asXML(), wie diese getInnerXml($e->asXML()). Diese Funktion funktioniert auch für Elemente mit vielen Präfixen (wie in meinem Fall, da ich keine aktuellen Methoden finden konnte, die die Konvertierung auf allen Kindknoten unterschiedlicher Präfixe durchführen).

Ausgang:

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

und dann verwenden, wie folgt aus::

string '' (length=0)  
string '' (length=0)  
string '' (length=0)  
string 'faf ' (length=4)  
string ' faf ' (length=6) 
1

Ich würde die SimpleXMLElement Klasse erweitern

echo $qa->answer->innerXML(); 
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; 
    } 
0

Wenn Sie nicht tun möchte den CDATA-Bereich streichen, Zeilen auskommentieren 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); 
} 
0

Sie können nur diese Funktion nutzen :)

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