PHP SimpleXML get InnerXml
Domanda
Ho bisogno di ottenere il contenuto HTML di answer
in questo po 'di XML:
<qa>
<question>Who are you?</question>
<answer>Who who, <strong>who who</strong>, <em>me</em></answer>
</qa>
Quindi voglio ottenere la stringa "Chi che, che che , me ".
Se ho la answer
come SimpleXMLElement
, posso chiamare asXML()
per ottenere "
Io preferirei modi che non comportano funzioni di stringa, ma se questo è l'unico modo, così sia.
Soluzione
Per quanto a mia conoscenza, non v'è built-in modo per ottenere questo. Mi piacerebbe consigliamo di provare SimpleDOM , che è una classe PHP che si estende SimpleXMLElement che offre metodi di convenienza per la maggior parte dei problemi comuni.
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();
In caso contrario, vedo due modi per farlo. Il primo sarebbe quello di convertire il vostro SimpleXMLElement
ad un DOMNode
poi ciclo sulla sua childNodes
per costruire il codice XML. L'altro sarebbe chiamare asXML()
quindi utilizzare le funzioni di stringa per rimuovere il nodo radice. Attenzione, però, a volte può tornare asXML()
markup che in realtà è fuori del nodo è stato chiamato da, come prologo o consigli d'uso di XML.
Altri suggerimenti
function SimpleXMLElement_innerXML($xml)
{
$innerXML= '';
foreach (dom_import_simplexml($xml)->childNodes as $child)
{
$innerXML .= $child->ownerDocument->saveXML( $child );
}
return $innerXML;
};
Questo funziona (anche se sembra davvero zoppo):
echo (string)$qa->answer;
soluzione più semplice è quella di implementare personalizzato ottenere InnerXml con semplice XML:
function simplexml_innerXML($node)
{
$content="";
foreach($node->children() as $child)
$content .= $child->asXml();
return $content;
}
Nel codice, sostituire $body_content = $el->asXml();
con $body_content = simplexml_innerXML($el);
Tuttavia, si potrebbe anche passare a un altro API che offre distinzione tra InnerXml (quello che stai cercando) e OuterXml (quello che si ottiene per ora). Microsoft Dom libary offre questa distinzione, ma purtroppo PHP DOM non lo fa.
ho scoperto che PHP XMLReader API offre questo distintion. Vedere ReadInnerXml (). Anche se questa API ha un approccio molto diverso per l'elaborazione XML. Provatelo.
Infine, vorrei sottolineare che XML non è destinato per estrarre i dati come sottostrutture, ma piuttosto come valore. Ecco perché si incorrere in problemi a trovare l'API destra. Sarebbe più 'standard' per memorizzare HTML sottostruttura come un valore (e la fuga tutti i tag), piuttosto che sotto-albero XML. Inoltre fate attenzione che alcuni synthax HTML non sono sempre compatibili XML (cioè
vs,
). Ad ogni modo, in pratica, ci si avvicina è sicuramente più conveniente per la modifica del file xml.
avrei estendere 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());
}
}
e quindi utilizzarlo in questo modo:
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>"));
?>
Dopo la ricerca di un po ', ho ricevuto alcuna soluzione di soddisfazione. Così ho scritto la mia propria funzione.
Questa funzione otterrà esattamente il contenuto innerXml
(tra cui bianco-spazio, naturalmente).
Per utilizzarlo, passare il risultato della funzione asXML()
, come questo getInnerXml($e->asXML())
. Questo lavoro di funzione per gli elementi con molti prefissi così (come il mio caso, come non ho potuto trovare nessuna metodi attuali che fanno la conversione su tutti i nodi figlio di diversi prefissi).
Output:
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;
}
Se non si vuole mettere a nudo sezione CDATA, commentare le linee 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);
}
Si può semplicemente utilizzare questa funzione:)
function innerXML( $node )
{
$name = $node->getName();
return preg_replace( '/((<'.$name.'[^>]*>)|(<\/'.$name.'>))/UD', "", $node->asXML() );
}
utilizzando regex si potrebbe fare questo
preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);